blob: 535a2b2cc4733fd5c2dad780e8a9b65eaa16842f [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080018
Garfield Tan1c7bc862020-01-28 13:24:04 -080019#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070020#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070021#include <binder/Binder.h>
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -080022#include <input/Input.h>
Robert Carr803535b2018-08-02 16:38:15 -070023
Michael Wrightd02c5b62014-02-10 15:10:22 -080024#include <gtest/gtest.h>
25#include <linux/input.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080026#include <cinttypes>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070027#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080028#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080029#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080030
Garfield Tan1c7bc862020-01-28 13:24:04 -080031using android::base::StringPrintf;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080032using android::os::InputEventInjectionResult;
33using android::os::InputEventInjectionSync;
Michael Wright44753b12020-07-08 13:48:11 +010034using namespace android::flag_operators;
Garfield Tan1c7bc862020-01-28 13:24:04 -080035
Garfield Tane84e6f92019-08-29 17:28:41 -070036namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080037
38// An arbitrary time value.
39static const nsecs_t ARBITRARY_TIME = 1234;
40
41// An arbitrary device id.
42static const int32_t DEVICE_ID = 1;
43
Jeff Brownf086ddb2014-02-11 14:28:48 -080044// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080045static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080046
Michael Wrightd02c5b62014-02-10 15:10:22 -080047// An arbitrary injector pid / uid pair that has permission to inject events.
48static const int32_t INJECTOR_PID = 999;
49static const int32_t INJECTOR_UID = 1001;
50
chaviwd1c23182019-12-20 18:44:56 -080051struct PointF {
52 float x;
53 float y;
54};
Michael Wrightd02c5b62014-02-10 15:10:22 -080055
Gang Wang342c9272020-01-13 13:15:04 -050056/**
57 * Return a DOWN key event with KEYCODE_A.
58 */
59static KeyEvent getTestKeyEvent() {
60 KeyEvent event;
61
Garfield Tanfbe732e2020-01-24 11:26:14 -080062 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
63 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
64 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050065 return event;
66}
67
Michael Wrightd02c5b62014-02-10 15:10:22 -080068// --- FakeInputDispatcherPolicy ---
69
70class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
71 InputDispatcherConfiguration mConfig;
72
73protected:
74 virtual ~FakeInputDispatcherPolicy() {
75 }
76
77public:
78 FakeInputDispatcherPolicy() {
Jackal Guof9696682018-10-05 12:23:23 +080079 }
80
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080081 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080082 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
83 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080084 }
85
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080086 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080087 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
88 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080089 }
90
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070091 void assertFilterInputEventWasNotCalled() {
92 std::scoped_lock lock(mLock);
93 ASSERT_EQ(nullptr, mFilteredEvent);
94 }
Michael Wrightd02c5b62014-02-10 15:10:22 -080095
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080096 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070097 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080098 ASSERT_TRUE(mConfigurationChangedTime)
99 << "Timed out waiting for configuration changed call";
100 ASSERT_EQ(*mConfigurationChangedTime, when);
101 mConfigurationChangedTime = std::nullopt;
102 }
103
104 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700105 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800106 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800107 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800108 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
109 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
110 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
111 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
112 mLastNotifySwitch = std::nullopt;
113 }
114
chaviwfd6d3512019-03-25 13:23:49 -0700115 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700116 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800117 ASSERT_EQ(touchedToken, mOnPointerDownToken);
118 mOnPointerDownToken.clear();
119 }
120
121 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700122 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800123 ASSERT_TRUE(mOnPointerDownToken == nullptr)
124 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700125 }
126
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700127 // This function must be called soon after the expected ANR timer starts,
128 // because we are also checking how much time has passed.
Chris Yea209fde2020-07-22 13:54:51 -0700129 void assertNotifyAnrWasCalled(
130 std::chrono::nanoseconds timeout,
131 const std::shared_ptr<InputApplicationHandle>& expectedApplication,
132 const sp<IBinder>& expectedToken) {
133 std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> anrData;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700134 ASSERT_NO_FATAL_FAILURE(anrData = getNotifyAnrData(timeout));
135 ASSERT_EQ(expectedApplication, anrData.first);
136 ASSERT_EQ(expectedToken, anrData.second);
137 }
138
Chris Yea209fde2020-07-22 13:54:51 -0700139 std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> getNotifyAnrData(
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700140 std::chrono::nanoseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700141 const std::chrono::time_point start = std::chrono::steady_clock::now();
142 std::unique_lock lock(mLock);
143 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
144 android::base::ScopedLockAssertion assumeLocked(mLock);
145
146 // If there is an ANR, Dispatcher won't be idle because there are still events
147 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
148 // before checking if ANR was called.
149 // Since dispatcher is not guaranteed to call notifyAnr right away, we need to provide
150 // it some time to act. 100ms seems reasonable.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700151 mNotifyAnr.wait_for(lock, timeToWait, [this]() REQUIRES(mLock) {
152 return !mAnrApplications.empty() && !mAnrWindowTokens.empty();
153 });
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700154 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700155 if (mAnrApplications.empty() || mAnrWindowTokens.empty()) {
156 ADD_FAILURE() << "Did not receive ANR callback";
Siarhei Vishniakoua72accd2020-09-22 21:43:09 -0500157 return {};
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700158 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700159 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
160 // the dispatcher started counting before this function was called
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700161 if (std::chrono::abs(timeout - waited) > 100ms) {
162 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
163 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
164 << "ms, but waited "
165 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
166 << "ms instead";
167 }
Chris Yea209fde2020-07-22 13:54:51 -0700168 std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700169 std::make_pair(mAnrApplications.front(), mAnrWindowTokens.front());
170 mAnrApplications.pop();
171 mAnrWindowTokens.pop();
172 return result;
173 }
174
175 void assertNotifyAnrWasNotCalled() {
176 std::scoped_lock lock(mLock);
177 ASSERT_TRUE(mAnrApplications.empty());
178 ASSERT_TRUE(mAnrWindowTokens.empty());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700179 }
180
Garfield Tan1c7bc862020-01-28 13:24:04 -0800181 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
182 mConfig.keyRepeatTimeout = timeout;
183 mConfig.keyRepeatDelay = delay;
184 }
185
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700186 void setAnrTimeout(std::chrono::nanoseconds timeout) { mAnrTimeout = timeout; }
187
Michael Wrightd02c5b62014-02-10 15:10:22 -0800188private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700189 std::mutex mLock;
190 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
191 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
192 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
193 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800194
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700195 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700196 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700197 std::queue<sp<IBinder>> mAnrWindowTokens GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700198 std::condition_variable mNotifyAnr;
199 std::chrono::nanoseconds mAnrTimeout = 0ms;
200
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800201 virtual void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700202 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800203 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800204 }
205
Chris Yea209fde2020-07-22 13:54:51 -0700206 std::chrono::nanoseconds notifyAnr(const std::shared_ptr<InputApplicationHandle>& application,
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500207 const sp<IBinder>& windowToken,
208 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700209 std::scoped_lock lock(mLock);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700210 mAnrApplications.push(application);
211 mAnrWindowTokens.push(windowToken);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700212 mNotifyAnr.notify_all();
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500213 return mAnrTimeout;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800214 }
215
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700216 virtual void notifyInputChannelBroken(const sp<IBinder>&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800217
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700218 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700219
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700220 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800221 *outConfig = mConfig;
222 }
223
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800224 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700225 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800226 switch (inputEvent->getType()) {
227 case AINPUT_EVENT_TYPE_KEY: {
228 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800229 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800230 break;
231 }
232
233 case AINPUT_EVENT_TYPE_MOTION: {
234 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800235 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800236 break;
237 }
238 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800239 return true;
240 }
241
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700242 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800243
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700244 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800245
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700246 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*,
247 uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800248 return 0;
249 }
250
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700251 virtual bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t,
252 KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800253 return false;
254 }
255
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800256 virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
257 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700258 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800259 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
260 * essentially a passthrough for notifySwitch.
261 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800262 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800263 }
264
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700265 virtual void pokeUserActivity(nsecs_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800266
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700267 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800268 return false;
269 }
Jackal Guof9696682018-10-05 12:23:23 +0800270
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700271 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700272 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700273 mOnPointerDownToken = newToken;
274 }
275
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800276 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
277 int32_t displayId) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700278 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800279 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
280 ASSERT_EQ(mFilteredEvent->getType(), type);
281
282 if (type == AINPUT_EVENT_TYPE_KEY) {
283 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
284 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
285 EXPECT_EQ(keyEvent.getAction(), action);
286 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
287 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
288 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
289 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
290 EXPECT_EQ(motionEvent.getAction(), action);
291 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
292 } else {
293 FAIL() << "Unknown type: " << type;
294 }
295
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800296 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800297 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800298};
299
Michael Wrightd02c5b62014-02-10 15:10:22 -0800300// --- InputDispatcherTest ---
301
302class InputDispatcherTest : public testing::Test {
303protected:
304 sp<FakeInputDispatcherPolicy> mFakePolicy;
305 sp<InputDispatcher> mDispatcher;
306
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700307 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800308 mFakePolicy = new FakeInputDispatcherPolicy();
309 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800310 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
311 //Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700312 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800313 }
314
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700315 virtual void TearDown() override {
316 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800317 mFakePolicy.clear();
318 mDispatcher.clear();
319 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700320
321 /**
322 * Used for debugging when writing the test
323 */
324 void dumpDispatcherState() {
325 std::string dump;
326 mDispatcher->dump(dump);
327 std::stringstream ss(dump);
328 std::string to;
329
330 while (std::getline(ss, to, '\n')) {
331 ALOGE("%s", to.c_str());
332 }
333 }
Vishnu Nair958da932020-08-21 17:12:37 -0700334
335 void setFocusedWindow(const sp<InputWindowHandle>& window,
336 const sp<InputWindowHandle>& focusedWindow = nullptr) {
337 FocusRequest request;
338 request.token = window->getToken();
339 if (focusedWindow) {
340 request.focusedToken = focusedWindow->getToken();
341 }
342 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
343 request.displayId = window->getInfo()->displayId;
344 mDispatcher->setFocusedWindow(request);
345 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800346};
347
348
349TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
350 KeyEvent event;
351
352 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800353 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
354 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600355 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
356 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800357 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700358 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800359 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800360 << "Should reject key events with undefined action.";
361
362 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800363 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
364 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600365 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800366 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700367 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800368 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800369 << "Should reject key events with ACTION_MULTIPLE.";
370}
371
372TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
373 MotionEvent event;
374 PointerProperties pointerProperties[MAX_POINTERS + 1];
375 PointerCoords pointerCoords[MAX_POINTERS + 1];
376 for (int i = 0; i <= MAX_POINTERS; i++) {
377 pointerProperties[i].clear();
378 pointerProperties[i].id = i;
379 pointerCoords[i].clear();
380 }
381
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800382 // Some constants commonly used below
383 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
384 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
385 constexpr int32_t metaState = AMETA_NONE;
386 constexpr MotionClassification classification = MotionClassification::NONE;
387
chaviw9eaa22c2020-07-01 16:21:27 -0700388 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800389 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800390 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700391 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
392 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600393 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700394 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800395 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700396 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800397 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800398 << "Should reject motion events with undefined action.";
399
400 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800401 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700402 AMOTION_EVENT_ACTION_POINTER_DOWN |
403 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700404 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
405 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
406 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
407 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800408 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700409 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800410 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800411 << "Should reject motion events with pointer down index too large.";
412
Garfield Tanfbe732e2020-01-24 11:26:14 -0800413 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700414 AMOTION_EVENT_ACTION_POINTER_DOWN |
415 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700416 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
417 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
418 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
419 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800420 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700421 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800422 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800423 << "Should reject motion events with pointer down index too small.";
424
425 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800426 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700427 AMOTION_EVENT_ACTION_POINTER_UP |
428 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700429 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
430 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
431 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
432 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800433 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700434 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800435 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800436 << "Should reject motion events with pointer up index too large.";
437
Garfield Tanfbe732e2020-01-24 11:26:14 -0800438 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700439 AMOTION_EVENT_ACTION_POINTER_UP |
440 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700441 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
442 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
443 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
444 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800445 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700446 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800447 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800448 << "Should reject motion events with pointer up index too small.";
449
450 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800451 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
452 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700453 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
454 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700455 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800456 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700457 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800458 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800459 << "Should reject motion events with 0 pointers.";
460
Garfield Tanfbe732e2020-01-24 11:26:14 -0800461 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
462 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700463 identityTransform, 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*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800466 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700467 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800468 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800469 << "Should reject motion events with more than MAX_POINTERS pointers.";
470
471 // Rejects motion events with invalid pointer ids.
472 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800473 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
474 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700475 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
476 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700477 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800478 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700479 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800480 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800481 << "Should reject motion events with pointer ids less than 0.";
482
483 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800484 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
485 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700486 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
487 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700488 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800489 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700490 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800491 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800492 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
493
494 // Rejects motion events with duplicate pointer ids.
495 pointerProperties[0].id = 1;
496 pointerProperties[1].id = 1;
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,
chaviw9eaa22c2020-07-01 16:21:27 -0700499 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
500 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700501 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800502 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700503 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800504 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800505 << "Should reject motion events with duplicate pointer ids.";
506}
507
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800508/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
509
510TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
511 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800512 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800513 mDispatcher->notifyConfigurationChanged(&args);
514 ASSERT_TRUE(mDispatcher->waitForIdle());
515
516 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
517}
518
519TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800520 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
521 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800522 mDispatcher->notifySwitch(&args);
523
524 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
525 args.policyFlags |= POLICY_FLAG_TRUSTED;
526 mFakePolicy->assertNotifySwitchWasCalled(args);
527}
528
Arthur Hungb92218b2018-08-14 12:00:21 +0800529// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700530static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700531static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
Arthur Hungb92218b2018-08-14 12:00:21 +0800532
533class FakeApplicationHandle : public InputApplicationHandle {
534public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700535 FakeApplicationHandle() {
536 mInfo.name = "Fake Application";
537 mInfo.token = new BBinder();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500538 mInfo.dispatchingTimeoutMillis =
539 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700540 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800541 virtual ~FakeApplicationHandle() {}
542
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700543 virtual bool updateInfo() override {
Arthur Hungb92218b2018-08-14 12:00:21 +0800544 return true;
545 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700546
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500547 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
548 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700549 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800550};
551
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800552class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800553public:
Garfield Tan15601662020-09-22 15:32:38 -0700554 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800555 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700556 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800557 }
558
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800559 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700560 InputEvent* event;
561 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
562 if (!consumeSeq) {
563 return nullptr;
564 }
565 finishEvent(*consumeSeq);
566 return event;
567 }
568
569 /**
570 * Receive an event without acknowledging it.
571 * Return the sequence number that could later be used to send finished signal.
572 */
573 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800574 uint32_t consumeSeq;
575 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800576
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800577 std::chrono::time_point start = std::chrono::steady_clock::now();
578 status_t status = WOULD_BLOCK;
579 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800580 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800581 &event);
582 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
583 if (elapsed > 100ms) {
584 break;
585 }
586 }
587
588 if (status == WOULD_BLOCK) {
589 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700590 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800591 }
592
593 if (status != OK) {
594 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700595 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800596 }
597 if (event == nullptr) {
598 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700599 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800600 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700601 if (outEvent != nullptr) {
602 *outEvent = event;
603 }
604 return consumeSeq;
605 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800606
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700607 /**
608 * To be used together with "receiveEvent" to complete the consumption of an event.
609 */
610 void finishEvent(uint32_t consumeSeq) {
611 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
612 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800613 }
614
615 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
616 int32_t expectedFlags) {
617 InputEvent* event = consume();
618
619 ASSERT_NE(nullptr, event) << mName.c_str()
620 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800621 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700622 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800623 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800624
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800625 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800626
Tiger Huang8664f8c2018-10-11 19:14:35 +0800627 switch (expectedEventType) {
628 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800629 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
630 EXPECT_EQ(expectedAction, keyEvent.getAction());
631 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800632 break;
633 }
634 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800635 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
636 EXPECT_EQ(expectedAction, motionEvent.getAction());
637 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800638 break;
639 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100640 case AINPUT_EVENT_TYPE_FOCUS: {
641 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
642 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800643 default: {
644 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
645 }
646 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800647 }
648
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100649 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
650 InputEvent* event = consume();
651 ASSERT_NE(nullptr, event) << mName.c_str()
652 << ": consumer should have returned non-NULL event.";
653 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
654 << "Got " << inputEventTypeToString(event->getType())
655 << " event instead of FOCUS event";
656
657 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
658 << mName.c_str() << ": event displayId should always be NONE.";
659
660 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
661 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
662 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
663 }
664
chaviwd1c23182019-12-20 18:44:56 -0800665 void assertNoEvents() {
666 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700667 if (event == nullptr) {
668 return;
669 }
670 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
671 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
672 ADD_FAILURE() << "Received key event "
673 << KeyEvent::actionToString(keyEvent.getAction());
674 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
675 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
676 ADD_FAILURE() << "Received motion event "
677 << MotionEvent::actionToString(motionEvent.getAction());
678 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
679 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
680 ADD_FAILURE() << "Received focus event, hasFocus = "
681 << (focusEvent.getHasFocus() ? "true" : "false");
682 }
683 FAIL() << mName.c_str()
684 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800685 }
686
687 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
688
689protected:
690 std::unique_ptr<InputConsumer> mConsumer;
691 PreallocatedInputEventFactory mEventFactory;
692
693 std::string mName;
694};
695
696class FakeWindowHandle : public InputWindowHandle {
697public:
698 static const int32_t WIDTH = 600;
699 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800700
Chris Yea209fde2020-07-22 13:54:51 -0700701 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
chaviwd1c23182019-12-20 18:44:56 -0800702 const sp<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500703 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -0800704 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500705 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -0700706 base::Result<std::unique_ptr<InputChannel>> channel =
707 dispatcher->createInputChannel(name);
708 token = (*channel)->getConnectionToken();
709 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -0800710 }
711
712 inputApplicationHandle->updateInfo();
713 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
714
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500715 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700716 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800717 mInfo.name = name;
Michael Wright44753b12020-07-08 13:48:11 +0100718 mInfo.type = InputWindowInfo::Type::APPLICATION;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500719 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
chaviwd1c23182019-12-20 18:44:56 -0800720 mInfo.frameLeft = 0;
721 mInfo.frameTop = 0;
722 mInfo.frameRight = WIDTH;
723 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -0700724 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -0800725 mInfo.globalScaleFactor = 1.0;
726 mInfo.touchableRegion.clear();
727 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
728 mInfo.visible = true;
Vishnu Nair47074b82020-08-14 11:54:47 -0700729 mInfo.focusable = false;
chaviwd1c23182019-12-20 18:44:56 -0800730 mInfo.hasWallpaper = false;
731 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800732 mInfo.ownerPid = INJECTOR_PID;
733 mInfo.ownerUid = INJECTOR_UID;
chaviwd1c23182019-12-20 18:44:56 -0800734 mInfo.displayId = displayId;
735 }
736
737 virtual bool updateInfo() { return true; }
738
Vishnu Nair47074b82020-08-14 11:54:47 -0700739 void setFocusable(bool focusable) { mInfo.focusable = focusable; }
chaviwd1c23182019-12-20 18:44:56 -0800740
Vishnu Nair958da932020-08-21 17:12:37 -0700741 void setVisible(bool visible) { mInfo.visible = visible; }
742
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700743 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500744 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700745 }
746
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700747 void setPaused(bool paused) { mInfo.paused = paused; }
748
chaviwd1c23182019-12-20 18:44:56 -0800749 void setFrame(const Rect& frame) {
750 mInfo.frameLeft = frame.left;
751 mInfo.frameTop = frame.top;
752 mInfo.frameRight = frame.right;
753 mInfo.frameBottom = frame.bottom;
chaviw1ff3d1e2020-07-01 15:53:47 -0700754 mInfo.transform.set(frame.left, frame.top);
chaviwd1c23182019-12-20 18:44:56 -0800755 mInfo.touchableRegion.clear();
756 mInfo.addTouchableRegion(frame);
757 }
758
Michael Wright44753b12020-07-08 13:48:11 +0100759 void setFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags = flags; }
chaviwd1c23182019-12-20 18:44:56 -0800760
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500761 void setInputFeatures(InputWindowInfo::Feature features) { mInfo.inputFeatures = features; }
762
chaviw9eaa22c2020-07-01 16:21:27 -0700763 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
764 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
765 }
766
767 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -0700768
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800769 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
770 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
771 expectedFlags);
772 }
773
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700774 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
775 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
776 }
777
Svet Ganov5d3bc372020-01-26 23:11:07 -0800778 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
779 int32_t expectedFlags = 0) {
780 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
781 expectedFlags);
782 }
783
784 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
785 int32_t expectedFlags = 0) {
786 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
787 expectedFlags);
788 }
789
790 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
791 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800792 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
793 expectedFlags);
794 }
795
Svet Ganov5d3bc372020-01-26 23:11:07 -0800796 void consumeMotionPointerDown(int32_t pointerIdx,
797 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) {
798 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN
799 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
800 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
801 }
802
803 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
804 int32_t expectedFlags = 0) {
805 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP
806 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
807 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
808 }
809
810 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
811 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000812 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
813 expectedFlags);
814 }
815
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100816 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
817 ASSERT_NE(mInputReceiver, nullptr)
818 << "Cannot consume events from a window with no receiver";
819 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
820 }
821
chaviwd1c23182019-12-20 18:44:56 -0800822 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
823 int32_t expectedFlags) {
824 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
825 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
826 expectedFlags);
827 }
828
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700829 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700830 if (mInputReceiver == nullptr) {
831 ADD_FAILURE() << "Invalid receive event on window with no receiver";
832 return std::nullopt;
833 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700834 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700835 }
836
837 void finishEvent(uint32_t sequenceNum) {
838 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
839 mInputReceiver->finishEvent(sequenceNum);
840 }
841
chaviwaf87b3e2019-10-01 16:59:28 -0700842 InputEvent* consume() {
843 if (mInputReceiver == nullptr) {
844 return nullptr;
845 }
846 return mInputReceiver->consume();
847 }
848
Arthur Hungb92218b2018-08-14 12:00:21 +0800849 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500850 if (mInputReceiver == nullptr &&
851 mInfo.inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL)) {
852 return; // Can't receive events if the window does not have input channel
853 }
854 ASSERT_NE(nullptr, mInputReceiver)
855 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -0800856 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800857 }
858
chaviwaf87b3e2019-10-01 16:59:28 -0700859 sp<IBinder> getToken() { return mInfo.token; }
860
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100861 const std::string& getName() { return mName; }
862
chaviwd1c23182019-12-20 18:44:56 -0800863private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100864 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800865 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700866 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800867};
868
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700869std::atomic<int32_t> FakeWindowHandle::sId{1};
870
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800871static InputEventInjectionResult injectKey(
872 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
873 int32_t displayId = ADISPLAY_ID_NONE,
874 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
875 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800876 KeyEvent event;
877 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
878
879 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800880 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700881 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
882 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800883
884 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700885 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
886 injectionTimeout,
887 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
Arthur Hungb92218b2018-08-14 12:00:21 +0800888}
889
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800890static InputEventInjectionResult injectKeyDown(const sp<InputDispatcher>& dispatcher,
891 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700892 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
893}
894
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800895static InputEventInjectionResult injectKeyUp(const sp<InputDispatcher>& dispatcher,
896 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700897 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
898}
899
Garfield Tandf26e862020-07-01 20:18:19 -0700900class PointerBuilder {
901public:
902 PointerBuilder(int32_t id, int32_t toolType) {
903 mProperties.clear();
904 mProperties.id = id;
905 mProperties.toolType = toolType;
906 mCoords.clear();
907 }
908
909 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
910
911 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
912
913 PointerBuilder& axis(int32_t axis, float value) {
914 mCoords.setAxisValue(axis, value);
915 return *this;
916 }
917
918 PointerProperties buildProperties() const { return mProperties; }
919
920 PointerCoords buildCoords() const { return mCoords; }
921
922private:
923 PointerProperties mProperties;
924 PointerCoords mCoords;
925};
926
927class MotionEventBuilder {
928public:
929 MotionEventBuilder(int32_t action, int32_t source) {
930 mAction = action;
931 mSource = source;
932 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
933 }
934
935 MotionEventBuilder& eventTime(nsecs_t eventTime) {
936 mEventTime = eventTime;
937 return *this;
938 }
939
940 MotionEventBuilder& displayId(int32_t displayId) {
941 mDisplayId = displayId;
942 return *this;
943 }
944
945 MotionEventBuilder& actionButton(int32_t actionButton) {
946 mActionButton = actionButton;
947 return *this;
948 }
949
950 MotionEventBuilder& buttonState(int32_t actionButton) {
951 mActionButton = actionButton;
952 return *this;
953 }
954
955 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
956 mRawXCursorPosition = rawXCursorPosition;
957 return *this;
958 }
959
960 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
961 mRawYCursorPosition = rawYCursorPosition;
962 return *this;
963 }
964
965 MotionEventBuilder& pointer(PointerBuilder pointer) {
966 mPointers.push_back(pointer);
967 return *this;
968 }
969
970 MotionEvent build() {
971 std::vector<PointerProperties> pointerProperties;
972 std::vector<PointerCoords> pointerCoords;
973 for (const PointerBuilder& pointer : mPointers) {
974 pointerProperties.push_back(pointer.buildProperties());
975 pointerCoords.push_back(pointer.buildCoords());
976 }
977
978 // Set mouse cursor position for the most common cases to avoid boilerplate.
979 if (mSource == AINPUT_SOURCE_MOUSE &&
980 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
981 mPointers.size() == 1) {
982 mRawXCursorPosition = pointerCoords[0].getX();
983 mRawYCursorPosition = pointerCoords[0].getY();
984 }
985
986 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -0700987 ui::Transform identityTransform;
Garfield Tandf26e862020-07-01 20:18:19 -0700988 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
989 mAction, mActionButton, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -0700990 mButtonState, MotionClassification::NONE, identityTransform,
991 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
992 mRawYCursorPosition, mEventTime, mEventTime, mPointers.size(),
993 pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -0700994
995 return event;
996 }
997
998private:
999 int32_t mAction;
1000 int32_t mSource;
1001 nsecs_t mEventTime;
1002 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1003 int32_t mActionButton{0};
1004 int32_t mButtonState{0};
1005 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1006 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1007
1008 std::vector<PointerBuilder> mPointers;
1009};
1010
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001011static InputEventInjectionResult injectMotionEvent(
Garfield Tandf26e862020-07-01 20:18:19 -07001012 const sp<InputDispatcher>& dispatcher, const MotionEvent& event,
1013 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001014 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT) {
Garfield Tandf26e862020-07-01 20:18:19 -07001015 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
1016 injectionTimeout,
1017 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
1018}
1019
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001020static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001021 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
1022 const PointF& position,
1023 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001024 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1025 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001026 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001027 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Garfield Tandf26e862020-07-01 20:18:19 -07001028 MotionEvent event = MotionEventBuilder(action, source)
1029 .displayId(displayId)
1030 .eventTime(eventTime)
1031 .rawXCursorPosition(cursorPosition.x)
1032 .rawYCursorPosition(cursorPosition.y)
1033 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1034 .x(position.x)
1035 .y(position.y))
1036 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001037
1038 // Inject event until dispatch out.
Garfield Tandf26e862020-07-01 20:18:19 -07001039 return injectMotionEvent(dispatcher, event);
Arthur Hungb92218b2018-08-14 12:00:21 +08001040}
1041
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001042static InputEventInjectionResult injectMotionDown(const sp<InputDispatcher>& dispatcher,
1043 int32_t source, int32_t displayId,
1044 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001045 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001046}
1047
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001048static InputEventInjectionResult injectMotionUp(const sp<InputDispatcher>& dispatcher,
1049 int32_t source, int32_t displayId,
1050 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001051 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001052}
1053
Jackal Guof9696682018-10-05 12:23:23 +08001054static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1055 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1056 // Define a valid key event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001057 NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
1058 POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A,
1059 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001060
1061 return args;
1062}
1063
chaviwd1c23182019-12-20 18:44:56 -08001064static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1065 const std::vector<PointF>& points) {
1066 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001067 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1068 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1069 }
1070
chaviwd1c23182019-12-20 18:44:56 -08001071 PointerProperties pointerProperties[pointerCount];
1072 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001073
chaviwd1c23182019-12-20 18:44:56 -08001074 for (size_t i = 0; i < pointerCount; i++) {
1075 pointerProperties[i].clear();
1076 pointerProperties[i].id = i;
1077 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001078
chaviwd1c23182019-12-20 18:44:56 -08001079 pointerCoords[i].clear();
1080 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1081 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1082 }
Jackal Guof9696682018-10-05 12:23:23 +08001083
1084 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1085 // Define a valid motion event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001086 NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001087 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1088 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001089 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1090 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001091 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1092 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001093
1094 return args;
1095}
1096
chaviwd1c23182019-12-20 18:44:56 -08001097static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1098 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1099}
1100
Arthur Hungb92218b2018-08-14 12:00:21 +08001101TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001102 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001103 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
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, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1108 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1109 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001110
1111 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001112 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001113}
1114
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001115/**
1116 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1117 * To ensure that window receives only events that were directly inside of it, add
1118 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1119 * when finding touched windows.
1120 * This test serves as a sanity check for the next test, where setInputWindows is
1121 * called twice.
1122 */
1123TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001124 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001125 sp<FakeWindowHandle> window =
1126 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1127 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001128 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001129
1130 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001131 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001132 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1133 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001134 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001135
1136 // Window should receive motion event.
1137 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1138}
1139
1140/**
1141 * Calling setInputWindows twice, with the same info, should not cause any issues.
1142 * To ensure that window receives only events that were directly inside of it, add
1143 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1144 * when finding touched windows.
1145 */
1146TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001147 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001148 sp<FakeWindowHandle> window =
1149 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1150 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001151 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001152
1153 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1154 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001155 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001156 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1157 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001158 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001159
1160 // Window should receive motion event.
1161 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1162}
1163
Arthur Hungb92218b2018-08-14 12:00:21 +08001164// The foreground window should receive the first touch down event.
1165TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001166 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001167 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1168 ADISPLAY_ID_DEFAULT);
1169 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1170 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001171
Arthur Hung72d8dc32020-03-28 00:48:39 +00001172 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001173 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1174 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1175 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001176
1177 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001178 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001179 windowSecond->assertNoEvents();
1180}
1181
Garfield Tandf26e862020-07-01 20:18:19 -07001182TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001183 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001184 sp<FakeWindowHandle> windowLeft =
1185 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1186 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001187 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001188 sp<FakeWindowHandle> windowRight =
1189 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1190 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001191 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001192
1193 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1194
1195 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
1196
1197 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001198 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001199 injectMotionEvent(mDispatcher,
1200 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1201 AINPUT_SOURCE_MOUSE)
1202 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1203 .x(900)
1204 .y(400))
1205 .build()));
1206 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1207 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1208 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1209 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1210
1211 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001213 injectMotionEvent(mDispatcher,
1214 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1215 AINPUT_SOURCE_MOUSE)
1216 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1217 .x(300)
1218 .y(400))
1219 .build()));
1220 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1221 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1222 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1223 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1224 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1225 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1226
1227 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001229 injectMotionEvent(mDispatcher,
1230 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1231 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1232 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1233 .x(300)
1234 .y(400))
1235 .build()));
1236 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1237
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001239 injectMotionEvent(mDispatcher,
1240 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1241 AINPUT_SOURCE_MOUSE)
1242 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1243 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1244 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1245 .x(300)
1246 .y(400))
1247 .build()));
1248 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1249 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1250
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001251 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001252 injectMotionEvent(mDispatcher,
1253 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1254 AINPUT_SOURCE_MOUSE)
1255 .buttonState(0)
1256 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1257 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1258 .x(300)
1259 .y(400))
1260 .build()));
1261 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1262 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1263
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001264 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001265 injectMotionEvent(mDispatcher,
1266 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1267 .buttonState(0)
1268 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1269 .x(300)
1270 .y(400))
1271 .build()));
1272 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1273
1274 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001275 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001276 injectMotionEvent(mDispatcher,
1277 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1278 AINPUT_SOURCE_MOUSE)
1279 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1280 .x(900)
1281 .y(400))
1282 .build()));
1283 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1284 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1285 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1286 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1287 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1288 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1289}
1290
1291// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
1292// directly in this test.
1293TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001294 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001295 sp<FakeWindowHandle> window =
1296 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1297 window->setFrame(Rect(0, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001298 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001299
1300 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1301
1302 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1303
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001304 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001305 injectMotionEvent(mDispatcher,
1306 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
1307 AINPUT_SOURCE_MOUSE)
1308 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1309 .x(300)
1310 .y(400))
1311 .build()));
1312 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1313 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1314
1315 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001317 injectMotionEvent(mDispatcher,
1318 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1319 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1320 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1321 .x(300)
1322 .y(400))
1323 .build()));
1324 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1325
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001326 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001327 injectMotionEvent(mDispatcher,
1328 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1329 AINPUT_SOURCE_MOUSE)
1330 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1331 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1332 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1333 .x(300)
1334 .y(400))
1335 .build()));
1336 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1337 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1338
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001339 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001340 injectMotionEvent(mDispatcher,
1341 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1342 AINPUT_SOURCE_MOUSE)
1343 .buttonState(0)
1344 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1345 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1346 .x(300)
1347 .y(400))
1348 .build()));
1349 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1350 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1351
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001352 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001353 injectMotionEvent(mDispatcher,
1354 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1355 .buttonState(0)
1356 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1357 .x(300)
1358 .y(400))
1359 .build()));
1360 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1361
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001362 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001363 injectMotionEvent(mDispatcher,
1364 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
1365 AINPUT_SOURCE_MOUSE)
1366 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1367 .x(300)
1368 .y(400))
1369 .build()));
1370 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1371 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1372}
1373
Garfield Tan00f511d2019-06-12 16:55:40 -07001374TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07001375 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07001376
1377 sp<FakeWindowHandle> windowLeft =
1378 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1379 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001380 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001381 sp<FakeWindowHandle> windowRight =
1382 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1383 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001384 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001385
1386 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1387
Arthur Hung72d8dc32020-03-28 00:48:39 +00001388 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001389
1390 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1391 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07001393 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001394 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001395 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001396 windowRight->assertNoEvents();
1397}
1398
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001399TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001400 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001401 sp<FakeWindowHandle> window =
1402 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07001403 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001404
Arthur Hung72d8dc32020-03-28 00:48:39 +00001405 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001406 setFocusedWindow(window);
1407
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001408 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001409
1410 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1411 mDispatcher->notifyKey(&keyArgs);
1412
1413 // Window should receive key down event.
1414 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1415
1416 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1417 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001418 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001419 mDispatcher->notifyDeviceReset(&args);
1420 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1421 AKEY_EVENT_FLAG_CANCELED);
1422}
1423
1424TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001425 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001426 sp<FakeWindowHandle> window =
1427 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1428
Arthur Hung72d8dc32020-03-28 00:48:39 +00001429 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001430
1431 NotifyMotionArgs motionArgs =
1432 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1433 ADISPLAY_ID_DEFAULT);
1434 mDispatcher->notifyMotion(&motionArgs);
1435
1436 // Window should receive motion down event.
1437 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1438
1439 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1440 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001441 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001442 mDispatcher->notifyDeviceReset(&args);
1443 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1444 0 /*expectedFlags*/);
1445}
1446
Svet Ganov5d3bc372020-01-26 23:11:07 -08001447TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07001448 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001449
1450 // Create a couple of windows
1451 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1452 "First Window", ADISPLAY_ID_DEFAULT);
1453 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1454 "Second Window", ADISPLAY_ID_DEFAULT);
1455
1456 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001457 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001458
1459 // Send down to the first window
1460 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1461 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1462 mDispatcher->notifyMotion(&downMotionArgs);
1463 // Only the first window should get the down event
1464 firstWindow->consumeMotionDown();
1465 secondWindow->assertNoEvents();
1466
1467 // Transfer touch focus to the second window
1468 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1469 // The first window gets cancel and the second gets down
1470 firstWindow->consumeMotionCancel();
1471 secondWindow->consumeMotionDown();
1472
1473 // Send up event to the second window
1474 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1475 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1476 mDispatcher->notifyMotion(&upMotionArgs);
1477 // The first window gets no events and the second gets up
1478 firstWindow->assertNoEvents();
1479 secondWindow->consumeMotionUp();
1480}
1481
1482TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001483 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001484
1485 PointF touchPoint = {10, 10};
1486
1487 // Create a couple of windows
1488 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1489 "First Window", ADISPLAY_ID_DEFAULT);
1490 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1491 "Second Window", ADISPLAY_ID_DEFAULT);
1492
1493 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001494 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001495
1496 // Send down to the first window
1497 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1498 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint});
1499 mDispatcher->notifyMotion(&downMotionArgs);
1500 // Only the first window should get the down event
1501 firstWindow->consumeMotionDown();
1502 secondWindow->assertNoEvents();
1503
1504 // Send pointer down to the first window
1505 NotifyMotionArgs pointerDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1506 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1507 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1508 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1509 // Only the first window should get the pointer down event
1510 firstWindow->consumeMotionPointerDown(1);
1511 secondWindow->assertNoEvents();
1512
1513 // Transfer touch focus to the second window
1514 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1515 // The first window gets cancel and the second gets down and pointer down
1516 firstWindow->consumeMotionCancel();
1517 secondWindow->consumeMotionDown();
1518 secondWindow->consumeMotionPointerDown(1);
1519
1520 // Send pointer up to the second window
1521 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1522 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1523 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1524 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1525 // The first window gets nothing and the second gets pointer up
1526 firstWindow->assertNoEvents();
1527 secondWindow->consumeMotionPointerUp(1);
1528
1529 // Send up event to the second window
1530 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1531 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1532 mDispatcher->notifyMotion(&upMotionArgs);
1533 // The first window gets nothing and the second gets up
1534 firstWindow->assertNoEvents();
1535 secondWindow->consumeMotionUp();
1536}
1537
1538TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001539 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001540
1541 // Create a non touch modal window that supports split touch
1542 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1543 "First Window", ADISPLAY_ID_DEFAULT);
1544 firstWindow->setFrame(Rect(0, 0, 600, 400));
Michael Wright44753b12020-07-08 13:48:11 +01001545 firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1546 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001547
1548 // Create a non touch modal window that supports split touch
1549 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1550 "Second Window", ADISPLAY_ID_DEFAULT);
1551 secondWindow->setFrame(Rect(0, 400, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001552 secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1553 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001554
1555 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001556 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001557
1558 PointF pointInFirst = {300, 200};
1559 PointF pointInSecond = {300, 600};
1560
1561 // Send down to the first window
1562 NotifyMotionArgs firstDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1563 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst});
1564 mDispatcher->notifyMotion(&firstDownMotionArgs);
1565 // Only the first window should get the down event
1566 firstWindow->consumeMotionDown();
1567 secondWindow->assertNoEvents();
1568
1569 // Send down to the second window
1570 NotifyMotionArgs secondDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1571 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1572 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1573 mDispatcher->notifyMotion(&secondDownMotionArgs);
1574 // The first window gets a move and the second a down
1575 firstWindow->consumeMotionMove();
1576 secondWindow->consumeMotionDown();
1577
1578 // Transfer touch focus to the second window
1579 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1580 // The first window gets cancel and the new gets pointer down (it already saw down)
1581 firstWindow->consumeMotionCancel();
1582 secondWindow->consumeMotionPointerDown(1);
1583
1584 // Send pointer up to the second window
1585 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1586 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1587 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1588 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1589 // The first window gets nothing and the second gets pointer up
1590 firstWindow->assertNoEvents();
1591 secondWindow->consumeMotionPointerUp(1);
1592
1593 // Send up event to the second window
1594 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1595 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1596 mDispatcher->notifyMotion(&upMotionArgs);
1597 // The first window gets nothing and the second gets up
1598 firstWindow->assertNoEvents();
1599 secondWindow->consumeMotionUp();
1600}
1601
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001602TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001603 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001604 sp<FakeWindowHandle> window =
1605 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1606
Vishnu Nair47074b82020-08-14 11:54:47 -07001607 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001608 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001609 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001610
1611 window->consumeFocusEvent(true);
1612
1613 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1614 mDispatcher->notifyKey(&keyArgs);
1615
1616 // Window should receive key down event.
1617 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1618}
1619
1620TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001621 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001622 sp<FakeWindowHandle> window =
1623 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1624
Arthur Hung72d8dc32020-03-28 00:48:39 +00001625 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001626
1627 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1628 mDispatcher->notifyKey(&keyArgs);
1629 mDispatcher->waitForIdle();
1630
1631 window->assertNoEvents();
1632}
1633
1634// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1635TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07001636 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001637 sp<FakeWindowHandle> window =
1638 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1639
Arthur Hung72d8dc32020-03-28 00:48:39 +00001640 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001641
1642 // Send key
1643 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1644 mDispatcher->notifyKey(&keyArgs);
1645 // Send motion
1646 NotifyMotionArgs motionArgs =
1647 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1648 ADISPLAY_ID_DEFAULT);
1649 mDispatcher->notifyMotion(&motionArgs);
1650
1651 // Window should receive only the motion event
1652 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1653 window->assertNoEvents(); // Key event or focus event will not be received
1654}
1655
chaviwd1c23182019-12-20 18:44:56 -08001656class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001657public:
1658 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001659 int32_t displayId, bool isGestureMonitor = false) {
Garfield Tan15601662020-09-22 15:32:38 -07001660 base::Result<std::unique_ptr<InputChannel>> channel =
1661 dispatcher->createInputMonitor(displayId, isGestureMonitor, name);
1662 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00001663 }
1664
chaviwd1c23182019-12-20 18:44:56 -08001665 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1666
1667 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1668 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1669 expectedDisplayId, expectedFlags);
1670 }
1671
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001672 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
1673
1674 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1675
chaviwd1c23182019-12-20 18:44:56 -08001676 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1677 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1678 expectedDisplayId, expectedFlags);
1679 }
1680
1681 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1682 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1683 expectedDisplayId, expectedFlags);
1684 }
1685
1686 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1687
1688private:
1689 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001690};
1691
1692// Tests for gesture monitors
1693TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07001694 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001695 sp<FakeWindowHandle> window =
1696 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001697 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001698
chaviwd1c23182019-12-20 18:44:56 -08001699 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1700 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001701
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00001703 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001704 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00001705 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001706 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001707}
1708
1709TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07001710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001711 sp<FakeWindowHandle> window =
1712 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1713
1714 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07001715 window->setFocusable(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001716
Arthur Hung72d8dc32020-03-28 00:48:39 +00001717 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001718 setFocusedWindow(window);
1719
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001720 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001721
chaviwd1c23182019-12-20 18:44:56 -08001722 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1723 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001724
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001725 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1726 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00001727 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001728 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001729}
1730
1731TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001732 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001733 sp<FakeWindowHandle> window =
1734 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001735 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001736
chaviwd1c23182019-12-20 18:44:56 -08001737 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1738 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001739
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001740 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00001741 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001742 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00001743 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001744 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001745
1746 window->releaseChannel();
1747
chaviwd1c23182019-12-20 18:44:56 -08001748 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001749
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00001751 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001752 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001753 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001754}
1755
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001756TEST_F(InputDispatcherTest, UnresponsiveGestureMonitor_GetsAnr) {
1757 FakeMonitorReceiver monitor =
1758 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
1759 true /*isGestureMonitor*/);
1760
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001762 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
1763 std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
1764 ASSERT_TRUE(consumeSeq);
1765
1766 mFakePolicy->assertNotifyAnrWasCalled(DISPATCHING_TIMEOUT, nullptr, monitor.getToken());
1767 monitor.finishEvent(*consumeSeq);
1768 ASSERT_TRUE(mDispatcher->waitForIdle());
1769}
1770
chaviw81e2bb92019-12-18 15:03:51 -08001771TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001772 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
chaviw81e2bb92019-12-18 15:03:51 -08001773 sp<FakeWindowHandle> window =
1774 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1775
Arthur Hung72d8dc32020-03-28 00:48:39 +00001776 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08001777
1778 NotifyMotionArgs motionArgs =
1779 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1780 ADISPLAY_ID_DEFAULT);
1781
1782 mDispatcher->notifyMotion(&motionArgs);
1783 // Window should receive motion down event.
1784 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1785
1786 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001787 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08001788 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1789 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1790 motionArgs.pointerCoords[0].getX() - 10);
1791
1792 mDispatcher->notifyMotion(&motionArgs);
1793 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1794 0 /*expectedFlags*/);
1795}
1796
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001797/**
1798 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1799 * the device default right away. In the test scenario, we check both the default value,
1800 * and the action of enabling / disabling.
1801 */
1802TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07001803 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001804 sp<FakeWindowHandle> window =
1805 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1806
1807 // Set focused application.
1808 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07001809 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001810
1811 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00001812 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001813 setFocusedWindow(window);
1814
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001815 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1816
1817 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07001818 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001819 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001820 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1821
1822 SCOPED_TRACE("Disable touch mode");
1823 mDispatcher->setInTouchMode(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07001824 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001825 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001826 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001827 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1828
1829 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07001830 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001831 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001832 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1833
1834 SCOPED_TRACE("Enable touch mode again");
1835 mDispatcher->setInTouchMode(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07001836 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001837 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001838 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001839 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1840
1841 window->assertNoEvents();
1842}
1843
Gang Wange9087892020-01-07 12:17:14 -05001844TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001845 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Gang Wange9087892020-01-07 12:17:14 -05001846 sp<FakeWindowHandle> window =
1847 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1848
1849 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07001850 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05001851
Arthur Hung72d8dc32020-03-28 00:48:39 +00001852 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001853 setFocusedWindow(window);
1854
Gang Wange9087892020-01-07 12:17:14 -05001855 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1856
1857 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1858 mDispatcher->notifyKey(&keyArgs);
1859
1860 InputEvent* event = window->consume();
1861 ASSERT_NE(event, nullptr);
1862
1863 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1864 ASSERT_NE(verified, nullptr);
1865 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
1866
1867 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
1868 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
1869 ASSERT_EQ(keyArgs.source, verified->source);
1870 ASSERT_EQ(keyArgs.displayId, verified->displayId);
1871
1872 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
1873
1874 ASSERT_EQ(keyArgs.action, verifiedKey.action);
1875 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05001876 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
1877 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
1878 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
1879 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
1880 ASSERT_EQ(0, verifiedKey.repeatCount);
1881}
1882
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001883TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001884 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001885 sp<FakeWindowHandle> window =
1886 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1887
1888 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1889
Arthur Hung72d8dc32020-03-28 00:48:39 +00001890 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001891
1892 NotifyMotionArgs motionArgs =
1893 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1894 ADISPLAY_ID_DEFAULT);
1895 mDispatcher->notifyMotion(&motionArgs);
1896
1897 InputEvent* event = window->consume();
1898 ASSERT_NE(event, nullptr);
1899
1900 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1901 ASSERT_NE(verified, nullptr);
1902 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
1903
1904 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
1905 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
1906 EXPECT_EQ(motionArgs.source, verified->source);
1907 EXPECT_EQ(motionArgs.displayId, verified->displayId);
1908
1909 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
1910
1911 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
1912 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
1913 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
1914 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
1915 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
1916 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
1917 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
1918}
1919
chaviw09c8d2d2020-08-24 15:48:26 -07001920/**
1921 * Ensure that separate calls to sign the same data are generating the same key.
1922 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
1923 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
1924 * tests.
1925 */
1926TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
1927 KeyEvent event = getTestKeyEvent();
1928 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
1929
1930 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
1931 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
1932 ASSERT_EQ(hmac1, hmac2);
1933}
1934
1935/**
1936 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
1937 */
1938TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
1939 KeyEvent event = getTestKeyEvent();
1940 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
1941 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
1942
1943 verifiedEvent.deviceId += 1;
1944 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
1945
1946 verifiedEvent.source += 1;
1947 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
1948
1949 verifiedEvent.eventTimeNanos += 1;
1950 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
1951
1952 verifiedEvent.displayId += 1;
1953 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
1954
1955 verifiedEvent.action += 1;
1956 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
1957
1958 verifiedEvent.downTimeNanos += 1;
1959 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
1960
1961 verifiedEvent.flags += 1;
1962 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
1963
1964 verifiedEvent.keyCode += 1;
1965 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
1966
1967 verifiedEvent.scanCode += 1;
1968 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
1969
1970 verifiedEvent.metaState += 1;
1971 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
1972
1973 verifiedEvent.repeatCount += 1;
1974 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
1975}
1976
Vishnu Nair958da932020-08-21 17:12:37 -07001977TEST_F(InputDispatcherTest, SetFocusedWindow) {
1978 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1979 sp<FakeWindowHandle> windowTop =
1980 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1981 sp<FakeWindowHandle> windowSecond =
1982 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
1983 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1984
1985 // Top window is also focusable but is not granted focus.
1986 windowTop->setFocusable(true);
1987 windowSecond->setFocusable(true);
1988 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
1989 setFocusedWindow(windowSecond);
1990
1991 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
1993 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07001994
1995 // Focused window should receive event.
1996 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
1997 windowTop->assertNoEvents();
1998}
1999
2000TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
2001 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2002 sp<FakeWindowHandle> window =
2003 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2004 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2005
2006 window->setFocusable(true);
2007 // Release channel for window is no longer valid.
2008 window->releaseChannel();
2009 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2010 setFocusedWindow(window);
2011
2012 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002013 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2014 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002015
2016 // window channel is invalid, so it should not receive any input event.
2017 window->assertNoEvents();
2018}
2019
2020TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
2021 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2022 sp<FakeWindowHandle> window =
2023 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2024 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2025
2026 // Window is not focusable.
2027 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2028 setFocusedWindow(window);
2029
2030 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002031 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2032 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002033
2034 // window is invalid, so it should not receive any input event.
2035 window->assertNoEvents();
2036}
2037
2038TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
2039 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2040 sp<FakeWindowHandle> windowTop =
2041 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2042 sp<FakeWindowHandle> windowSecond =
2043 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2044 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2045
2046 windowTop->setFocusable(true);
2047 windowSecond->setFocusable(true);
2048 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2049 setFocusedWindow(windowTop);
2050 windowTop->consumeFocusEvent(true);
2051
2052 setFocusedWindow(windowSecond, windowTop);
2053 windowSecond->consumeFocusEvent(true);
2054 windowTop->consumeFocusEvent(false);
2055
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2057 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002058
2059 // Focused window should receive event.
2060 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2061}
2062
2063TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
2064 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2065 sp<FakeWindowHandle> windowTop =
2066 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2067 sp<FakeWindowHandle> windowSecond =
2068 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2069 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2070
2071 windowTop->setFocusable(true);
2072 windowSecond->setFocusable(true);
2073 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2074 setFocusedWindow(windowSecond, windowTop);
2075
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002076 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2077 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002078
2079 // Event should be dropped.
2080 windowTop->assertNoEvents();
2081 windowSecond->assertNoEvents();
2082}
2083
2084TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
2085 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2086 sp<FakeWindowHandle> window =
2087 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2088 sp<FakeWindowHandle> previousFocusedWindow =
2089 new FakeWindowHandle(application, mDispatcher, "previousFocusedWindow",
2090 ADISPLAY_ID_DEFAULT);
2091 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2092
2093 window->setFocusable(true);
2094 previousFocusedWindow->setFocusable(true);
2095 window->setVisible(false);
2096 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
2097 setFocusedWindow(previousFocusedWindow);
2098 previousFocusedWindow->consumeFocusEvent(true);
2099
2100 // Requesting focus on invisible window takes focus from currently focused window.
2101 setFocusedWindow(window);
2102 previousFocusedWindow->consumeFocusEvent(false);
2103
2104 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002105 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07002106 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002107 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07002108
2109 // Window does not get focus event or key down.
2110 window->assertNoEvents();
2111
2112 // Window becomes visible.
2113 window->setVisible(true);
2114 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2115
2116 // Window receives focus event.
2117 window->consumeFocusEvent(true);
2118 // Focused window receives key down.
2119 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2120}
2121
Garfield Tan1c7bc862020-01-28 13:24:04 -08002122class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
2123protected:
2124 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
2125 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
2126
Chris Yea209fde2020-07-22 13:54:51 -07002127 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002128 sp<FakeWindowHandle> mWindow;
2129
2130 virtual void SetUp() override {
2131 mFakePolicy = new FakeInputDispatcherPolicy();
2132 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
2133 mDispatcher = new InputDispatcher(mFakePolicy);
2134 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
2135 ASSERT_EQ(OK, mDispatcher->start());
2136
2137 setUpWindow();
2138 }
2139
2140 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07002141 mApp = std::make_shared<FakeApplicationHandle>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08002142 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2143
Vishnu Nair47074b82020-08-14 11:54:47 -07002144 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002145 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002146 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002147 mWindow->consumeFocusEvent(true);
2148 }
2149
Chris Ye2ad95392020-09-01 13:44:44 -07002150 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08002151 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07002152 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002153 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
2154 mDispatcher->notifyKey(&keyArgs);
2155
2156 // Window should receive key down event.
2157 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2158 }
2159
2160 void expectKeyRepeatOnce(int32_t repeatCount) {
2161 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
2162 InputEvent* repeatEvent = mWindow->consume();
2163 ASSERT_NE(nullptr, repeatEvent);
2164
2165 uint32_t eventType = repeatEvent->getType();
2166 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
2167
2168 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
2169 uint32_t eventAction = repeatKeyEvent->getAction();
2170 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
2171 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
2172 }
2173
Chris Ye2ad95392020-09-01 13:44:44 -07002174 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08002175 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07002176 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002177 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
2178 mDispatcher->notifyKey(&keyArgs);
2179
2180 // Window should receive key down event.
2181 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
2182 0 /*expectedFlags*/);
2183 }
2184};
2185
2186TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Chris Ye2ad95392020-09-01 13:44:44 -07002187 sendAndConsumeKeyDown(1 /* deviceId */);
2188 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2189 expectKeyRepeatOnce(repeatCount);
2190 }
2191}
2192
2193TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
2194 sendAndConsumeKeyDown(1 /* deviceId */);
2195 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2196 expectKeyRepeatOnce(repeatCount);
2197 }
2198 sendAndConsumeKeyDown(2 /* deviceId */);
2199 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08002200 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2201 expectKeyRepeatOnce(repeatCount);
2202 }
2203}
2204
2205TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Chris Ye2ad95392020-09-01 13:44:44 -07002206 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002207 expectKeyRepeatOnce(1 /*repeatCount*/);
Chris Ye2ad95392020-09-01 13:44:44 -07002208 sendAndConsumeKeyUp(1 /* deviceId */);
2209 mWindow->assertNoEvents();
2210}
2211
2212TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
2213 sendAndConsumeKeyDown(1 /* deviceId */);
2214 expectKeyRepeatOnce(1 /*repeatCount*/);
2215 sendAndConsumeKeyDown(2 /* deviceId */);
2216 expectKeyRepeatOnce(1 /*repeatCount*/);
2217 // Stale key up from device 1.
2218 sendAndConsumeKeyUp(1 /* deviceId */);
2219 // Device 2 is still down, keep repeating
2220 expectKeyRepeatOnce(2 /*repeatCount*/);
2221 expectKeyRepeatOnce(3 /*repeatCount*/);
2222 // Device 2 key up
2223 sendAndConsumeKeyUp(2 /* deviceId */);
2224 mWindow->assertNoEvents();
2225}
2226
2227TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
2228 sendAndConsumeKeyDown(1 /* deviceId */);
2229 expectKeyRepeatOnce(1 /*repeatCount*/);
2230 sendAndConsumeKeyDown(2 /* deviceId */);
2231 expectKeyRepeatOnce(1 /*repeatCount*/);
2232 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
2233 sendAndConsumeKeyUp(2 /* deviceId */);
2234 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08002235 mWindow->assertNoEvents();
2236}
2237
2238TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Chris Ye2ad95392020-09-01 13:44:44 -07002239 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002240 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2241 InputEvent* repeatEvent = mWindow->consume();
2242 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2243 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
2244 IdGenerator::getSource(repeatEvent->getId()));
2245 }
2246}
2247
2248TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Chris Ye2ad95392020-09-01 13:44:44 -07002249 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002250
2251 std::unordered_set<int32_t> idSet;
2252 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2253 InputEvent* repeatEvent = mWindow->consume();
2254 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2255 int32_t id = repeatEvent->getId();
2256 EXPECT_EQ(idSet.end(), idSet.find(id));
2257 idSet.insert(id);
2258 }
2259}
2260
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002261/* Test InputDispatcher for MultiDisplay */
2262class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
2263public:
2264 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002265 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002266 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08002267
Chris Yea209fde2020-07-22 13:54:51 -07002268 application1 = std::make_shared<FakeApplicationHandle>();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002269 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
2270 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002271
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002272 // Set focus window for primary display, but focused display would be second one.
2273 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07002274 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002275 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002276 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002277 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08002278
Chris Yea209fde2020-07-22 13:54:51 -07002279 application2 = std::make_shared<FakeApplicationHandle>();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002280 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
2281 SECOND_DISPLAY_ID);
2282 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002283 // Set focus display to second one.
2284 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
2285 // Set focus window for second display.
2286 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07002287 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002288 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002289 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002290 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002291 }
2292
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002293 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002294 InputDispatcherTest::TearDown();
2295
Chris Yea209fde2020-07-22 13:54:51 -07002296 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002297 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07002298 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002299 windowInSecondary.clear();
2300 }
2301
2302protected:
Chris Yea209fde2020-07-22 13:54:51 -07002303 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002304 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07002305 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002306 sp<FakeWindowHandle> windowInSecondary;
2307};
2308
2309TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
2310 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2312 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2313 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002314 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08002315 windowInSecondary->assertNoEvents();
2316
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002317 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2319 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
2320 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08002321 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002322 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08002323}
2324
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002325TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08002326 // Test inject a key down with display id specified.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2328 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002329 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08002330 windowInSecondary->assertNoEvents();
2331
2332 // Test inject a key down without display id specified.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002333 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2334 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08002335 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002336 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08002337
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002338 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002339 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08002340
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002341 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002342 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
2343 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08002344
2345 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002346 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2347 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08002348 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002349 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08002350 windowInSecondary->assertNoEvents();
2351}
2352
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002353// Test per-display input monitors for motion event.
2354TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08002355 FakeMonitorReceiver monitorInPrimary =
2356 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2357 FakeMonitorReceiver monitorInSecondary =
2358 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002359
2360 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002361 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2362 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2363 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002364 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002365 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002366 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002367 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002368
2369 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002370 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2371 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
2372 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002373 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002374 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002375 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08002376 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002377
2378 // Test inject a non-pointer motion event.
2379 // If specific a display, it will dispatch to the focused window of particular display,
2380 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002381 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2382 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
2383 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002384 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002385 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002386 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002387 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002388}
2389
2390// Test per-display input monitors for key event.
2391TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
2392 //Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08002393 FakeMonitorReceiver monitorInPrimary =
2394 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2395 FakeMonitorReceiver monitorInSecondary =
2396 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002397
2398 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002399 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2400 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002401 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002402 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002403 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002404 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002405}
2406
Vishnu Nair958da932020-08-21 17:12:37 -07002407TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
2408 sp<FakeWindowHandle> secondWindowInPrimary =
2409 new FakeWindowHandle(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2410 secondWindowInPrimary->setFocusable(true);
2411 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
2412 setFocusedWindow(secondWindowInPrimary);
2413 windowInPrimary->consumeFocusEvent(false);
2414 secondWindowInPrimary->consumeFocusEvent(true);
2415
2416 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2418 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002419 windowInPrimary->assertNoEvents();
2420 windowInSecondary->assertNoEvents();
2421 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2422}
2423
Jackal Guof9696682018-10-05 12:23:23 +08002424class InputFilterTest : public InputDispatcherTest {
2425protected:
2426 static constexpr int32_t SECOND_DISPLAY_ID = 1;
2427
2428 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
2429 NotifyMotionArgs motionArgs;
2430
2431 motionArgs = generateMotionArgs(
2432 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
2433 mDispatcher->notifyMotion(&motionArgs);
2434 motionArgs = generateMotionArgs(
2435 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
2436 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002437 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002438 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002439 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002440 } else {
2441 mFakePolicy->assertFilterInputEventWasNotCalled();
2442 }
2443 }
2444
2445 void testNotifyKey(bool expectToBeFiltered) {
2446 NotifyKeyArgs keyArgs;
2447
2448 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2449 mDispatcher->notifyKey(&keyArgs);
2450 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
2451 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002452 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002453
2454 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002455 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002456 } else {
2457 mFakePolicy->assertFilterInputEventWasNotCalled();
2458 }
2459 }
2460};
2461
2462// Test InputFilter for MotionEvent
2463TEST_F(InputFilterTest, MotionEvent_InputFilter) {
2464 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
2465 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2466 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2467
2468 // Enable InputFilter
2469 mDispatcher->setInputFilterEnabled(true);
2470 // Test touch on both primary and second display, and check if both events are filtered.
2471 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
2472 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
2473
2474 // Disable InputFilter
2475 mDispatcher->setInputFilterEnabled(false);
2476 // Test touch on both primary and second display, and check if both events aren't filtered.
2477 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2478 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2479}
2480
2481// Test InputFilter for KeyEvent
2482TEST_F(InputFilterTest, KeyEvent_InputFilter) {
2483 // Since the InputFilter is disabled by default, check if key event aren't filtered.
2484 testNotifyKey(/*expectToBeFiltered*/ false);
2485
2486 // Enable InputFilter
2487 mDispatcher->setInputFilterEnabled(true);
2488 // Send a key event, and check if it is filtered.
2489 testNotifyKey(/*expectToBeFiltered*/ true);
2490
2491 // Disable InputFilter
2492 mDispatcher->setInputFilterEnabled(false);
2493 // Send a key event, and check if it isn't filtered.
2494 testNotifyKey(/*expectToBeFiltered*/ false);
2495}
2496
chaviwfd6d3512019-03-25 13:23:49 -07002497class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002498 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07002499 InputDispatcherTest::SetUp();
2500
Chris Yea209fde2020-07-22 13:54:51 -07002501 std::shared_ptr<FakeApplicationHandle> application =
2502 std::make_shared<FakeApplicationHandle>();
chaviwfd6d3512019-03-25 13:23:49 -07002503 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
2504 ADISPLAY_ID_DEFAULT);
2505 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
2506 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2507 // window.
Michael Wright44753b12020-07-08 13:48:11 +01002508 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002509
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002510 mFocusedWindow =
2511 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2512 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01002513 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002514
2515 // Set focused application.
2516 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002517 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07002518
2519 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002520 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002521 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002522 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07002523 }
2524
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002525 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07002526 InputDispatcherTest::TearDown();
2527
2528 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002529 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07002530 }
2531
2532protected:
2533 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002534 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002535 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07002536};
2537
2538// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2539// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
2540// the onPointerDownOutsideFocus callback.
2541TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002542 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002543 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2544 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002545 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002546 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002547
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002548 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07002549 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
2550}
2551
2552// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
2553// DOWN on the window that doesn't have focus. Ensure no window received the
2554// onPointerDownOutsideFocus callback.
2555TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002556 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002557 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002558 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002559 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002560
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002561 ASSERT_TRUE(mDispatcher->waitForIdle());
2562 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002563}
2564
2565// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
2566// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
2567TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002568 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2569 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002570 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002571
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002572 ASSERT_TRUE(mDispatcher->waitForIdle());
2573 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002574}
2575
2576// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2577// DOWN on the window that already has focus. Ensure no window received the
2578// onPointerDownOutsideFocus callback.
2579TEST_F(InputDispatcherOnPointerDownOutsideFocus,
2580 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002581 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002582 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002583 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002584 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002585 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002586
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002587 ASSERT_TRUE(mDispatcher->waitForIdle());
2588 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002589}
2590
chaviwaf87b3e2019-10-01 16:59:28 -07002591// These tests ensures we can send touch events to a single client when there are multiple input
2592// windows that point to the same client token.
2593class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
2594 virtual void SetUp() override {
2595 InputDispatcherTest::SetUp();
2596
Chris Yea209fde2020-07-22 13:54:51 -07002597 std::shared_ptr<FakeApplicationHandle> application =
2598 std::make_shared<FakeApplicationHandle>();
chaviwaf87b3e2019-10-01 16:59:28 -07002599 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
2600 ADISPLAY_ID_DEFAULT);
2601 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
2602 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
Michael Wright44753b12020-07-08 13:48:11 +01002603 mWindow1->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2604 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002605 mWindow1->setFrame(Rect(0, 0, 100, 100));
2606
2607 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
2608 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
Michael Wright44753b12020-07-08 13:48:11 +01002609 mWindow2->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2610 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002611 mWindow2->setFrame(Rect(100, 100, 200, 200));
2612
Arthur Hung72d8dc32020-03-28 00:48:39 +00002613 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07002614 }
2615
2616protected:
2617 sp<FakeWindowHandle> mWindow1;
2618 sp<FakeWindowHandle> mWindow2;
2619
2620 // Helper function to convert the point from screen coordinates into the window's space
2621 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07002622 vec2 vals = windowInfo->transform.transform(point.x, point.y);
2623 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07002624 }
2625
2626 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
2627 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002628 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07002629 InputEvent* event = window->consume();
2630
2631 ASSERT_NE(nullptr, event) << name.c_str()
2632 << ": consumer should have returned non-NULL event.";
2633
2634 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
2635 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
2636 << " event, got " << inputEventTypeToString(event->getType()) << " event";
2637
2638 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
2639 EXPECT_EQ(expectedAction, motionEvent.getAction());
2640
2641 for (size_t i = 0; i < points.size(); i++) {
2642 float expectedX = points[i].x;
2643 float expectedY = points[i].y;
2644
2645 EXPECT_EQ(expectedX, motionEvent.getX(i))
2646 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
2647 << ", got " << motionEvent.getX(i);
2648 EXPECT_EQ(expectedY, motionEvent.getY(i))
2649 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
2650 << ", got " << motionEvent.getY(i);
2651 }
2652 }
chaviw9eaa22c2020-07-01 16:21:27 -07002653
2654 void touchAndAssertPositions(int32_t action, std::vector<PointF> touchedPoints,
2655 std::vector<PointF> expectedPoints) {
2656 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
2657 ADISPLAY_ID_DEFAULT, touchedPoints);
2658 mDispatcher->notifyMotion(&motionArgs);
2659
2660 // Always consume from window1 since it's the window that has the InputReceiver
2661 consumeMotionEvent(mWindow1, action, expectedPoints);
2662 }
chaviwaf87b3e2019-10-01 16:59:28 -07002663};
2664
2665TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
2666 // Touch Window 1
2667 PointF touchedPoint = {10, 10};
2668 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002669 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002670
2671 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07002672 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002673
2674 // Touch Window 2
2675 touchedPoint = {150, 150};
2676 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002677 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002678}
2679
chaviw9eaa22c2020-07-01 16:21:27 -07002680TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
2681 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07002682 mWindow2->setWindowScale(0.5f, 0.5f);
2683
2684 // Touch Window 1
2685 PointF touchedPoint = {10, 10};
2686 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002687 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002688 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07002689 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002690
2691 // Touch Window 2
2692 touchedPoint = {150, 150};
2693 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002694 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
2695 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002696
chaviw9eaa22c2020-07-01 16:21:27 -07002697 // Update the transform so rotation is set
2698 mWindow2->setWindowTransform(0, -1, 1, 0);
2699 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2700 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002701}
2702
chaviw9eaa22c2020-07-01 16:21:27 -07002703TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002704 mWindow2->setWindowScale(0.5f, 0.5f);
2705
2706 // Touch Window 1
2707 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2708 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002709 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002710
2711 // Touch Window 2
2712 int32_t actionPointerDown =
2713 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002714 touchedPoints.push_back(PointF{150, 150});
2715 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2716 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002717
chaviw9eaa22c2020-07-01 16:21:27 -07002718 // Release Window 2
2719 int32_t actionPointerUp =
2720 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2721 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
2722 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002723
chaviw9eaa22c2020-07-01 16:21:27 -07002724 // Update the transform so rotation is set for Window 2
2725 mWindow2->setWindowTransform(0, -1, 1, 0);
2726 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2727 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002728}
2729
chaviw9eaa22c2020-07-01 16:21:27 -07002730TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002731 mWindow2->setWindowScale(0.5f, 0.5f);
2732
2733 // Touch Window 1
2734 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2735 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002736 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002737
2738 // Touch Window 2
2739 int32_t actionPointerDown =
2740 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002741 touchedPoints.push_back(PointF{150, 150});
2742 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002743
chaviw9eaa22c2020-07-01 16:21:27 -07002744 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002745
2746 // Move both windows
2747 touchedPoints = {{20, 20}, {175, 175}};
2748 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2749 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2750
chaviw9eaa22c2020-07-01 16:21:27 -07002751 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002752
chaviw9eaa22c2020-07-01 16:21:27 -07002753 // Release Window 2
2754 int32_t actionPointerUp =
2755 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2756 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
2757 expectedPoints.pop_back();
2758
2759 // Touch Window 2
2760 mWindow2->setWindowTransform(0, -1, 1, 0);
2761 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2762 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
2763
2764 // Move both windows
2765 touchedPoints = {{20, 20}, {175, 175}};
2766 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2767 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2768
2769 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002770}
2771
2772TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
2773 mWindow1->setWindowScale(0.5f, 0.5f);
2774
2775 // Touch Window 1
2776 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2777 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002778 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002779
2780 // Touch Window 2
2781 int32_t actionPointerDown =
2782 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002783 touchedPoints.push_back(PointF{150, 150});
2784 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002785
chaviw9eaa22c2020-07-01 16:21:27 -07002786 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002787
2788 // Move both windows
2789 touchedPoints = {{20, 20}, {175, 175}};
2790 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2791 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2792
chaviw9eaa22c2020-07-01 16:21:27 -07002793 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002794}
2795
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002796class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
2797 virtual void SetUp() override {
2798 InputDispatcherTest::SetUp();
2799
Chris Yea209fde2020-07-22 13:54:51 -07002800 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002801 mApplication->setDispatchingTimeout(20ms);
2802 mWindow =
2803 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2804 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05002805 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07002806 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002807 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2808 // window.
Michael Wright44753b12020-07-08 13:48:11 +01002809 mWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002810
2811 // Set focused application.
2812 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
2813
2814 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002815 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002816 mWindow->consumeFocusEvent(true);
2817 }
2818
2819 virtual void TearDown() override {
2820 InputDispatcherTest::TearDown();
2821 mWindow.clear();
2822 }
2823
2824protected:
Chris Yea209fde2020-07-22 13:54:51 -07002825 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002826 sp<FakeWindowHandle> mWindow;
2827 static constexpr PointF WINDOW_LOCATION = {20, 20};
2828
2829 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002830 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002831 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2832 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002833 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002834 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2835 WINDOW_LOCATION));
2836 }
2837};
2838
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002839// Send a tap and respond, which should not cause an ANR.
2840TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
2841 tapOnWindow();
2842 mWindow->consumeMotionDown();
2843 mWindow->consumeMotionUp();
2844 ASSERT_TRUE(mDispatcher->waitForIdle());
2845 mFakePolicy->assertNotifyAnrWasNotCalled();
2846}
2847
2848// Send a regular key and respond, which should not cause an ANR.
2849TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002850 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002851 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
2852 ASSERT_TRUE(mDispatcher->waitForIdle());
2853 mFakePolicy->assertNotifyAnrWasNotCalled();
2854}
2855
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05002856TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
2857 mWindow->setFocusable(false);
2858 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2859 mWindow->consumeFocusEvent(false);
2860
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002861 InputEventInjectionResult result =
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05002862 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002863 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
2864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05002865 // Key will not go to window because we have no focused window.
2866 // The 'no focused window' ANR timer should start instead.
2867
2868 // Now, the focused application goes away.
2869 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
2870 // The key should get dropped and there should be no ANR.
2871
2872 ASSERT_TRUE(mDispatcher->waitForIdle());
2873 mFakePolicy->assertNotifyAnrWasNotCalled();
2874}
2875
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002876// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002877// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
2878// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002879TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002881 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2882 WINDOW_LOCATION));
2883
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002884 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
2885 ASSERT_TRUE(sequenceNum);
2886 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2887 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002888
2889 // The remaining lines are not really needed for the test, but kept as a sanity check
2890 mWindow->finishEvent(*sequenceNum);
2891 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2892 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002893 ASSERT_TRUE(mDispatcher->waitForIdle());
2894}
2895
2896// Send a key to the app and have the app not respond right away.
2897TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
2898 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002899 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002900 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
2901 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002902 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002903 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002904 ASSERT_TRUE(mDispatcher->waitForIdle());
2905}
2906
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002907// We have a focused application, but no focused window
2908TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07002909 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002910 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2911 mWindow->consumeFocusEvent(false);
2912
2913 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002914 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002915 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2916 WINDOW_LOCATION));
2917 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
2918 mDispatcher->waitForIdle();
2919 mFakePolicy->assertNotifyAnrWasNotCalled();
2920
2921 // Once a focused event arrives, we get an ANR for this application
2922 // We specify the injection timeout to be smaller than the application timeout, to ensure that
2923 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002924 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002925 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002926 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
2927 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002928 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2929 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2930 ASSERT_TRUE(mDispatcher->waitForIdle());
2931}
2932
2933// We have a focused application, but no focused window
2934// If the policy wants to keep waiting on the focused window to be added, make sure
2935// that this timeout extension is honored and ANR is raised again.
2936TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_ExtendsAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07002937 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002938 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2939 mWindow->consumeFocusEvent(false);
2940 const std::chrono::duration timeout = 5ms;
2941 mFakePolicy->setAnrTimeout(timeout);
2942
2943 // Once a focused event arrives, we get an ANR for this application
2944 // We specify the injection timeout to be smaller than the application timeout, to ensure that
2945 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002946 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002947 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002948 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
2949 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002950 const std::chrono::duration appTimeout =
2951 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2952 mFakePolicy->assertNotifyAnrWasCalled(appTimeout, mApplication, nullptr /*windowToken*/);
2953
2954 // After the extended time has passed, ANR should be raised again
2955 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2956
2957 // If we stop extending the timeout, dispatcher should go to idle.
2958 // Another ANR may be raised during this time
2959 mFakePolicy->setAnrTimeout(0ms);
2960 ASSERT_TRUE(mDispatcher->waitForIdle());
2961}
2962
2963// We have a focused application, but no focused window
2964TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07002965 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002966 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2967 mWindow->consumeFocusEvent(false);
2968
2969 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002970 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002971 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002972 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
2973 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002974
2975 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2976 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2977
2978 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002979 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002980 ASSERT_TRUE(mDispatcher->waitForIdle());
2981 mWindow->assertNoEvents();
2982}
2983
2984/**
2985 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
2986 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
2987 * If we process 1 of the events, but ANR on the second event with the same timestamp,
2988 * the ANR mechanism should still work.
2989 *
2990 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
2991 * DOWN event, while not responding on the second one.
2992 */
2993TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
2994 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
2995 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2996 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
2997 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
2998 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002999 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003000
3001 // Now send ACTION_UP, with identical timestamp
3002 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3003 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
3004 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
3005 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003006 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003007
3008 // We have now sent down and up. Let's consume first event and then ANR on the second.
3009 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3010 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3011 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
3012}
3013
3014// If an app is not responding to a key event, gesture monitors should continue to receive
3015// new motion events
3016TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
3017 FakeMonitorReceiver monitor =
3018 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
3019 true /*isGestureMonitor*/);
3020
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003021 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3022 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003023 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003025
3026 // Stuck on the ACTION_UP
3027 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3028 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr, mWindow->getToken());
3029
3030 // New tap will go to the gesture monitor, but not to the window
3031 tapOnWindow();
3032 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3033 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3034
3035 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
3036 mDispatcher->waitForIdle();
3037 mWindow->assertNoEvents();
3038 monitor.assertNoEvents();
3039}
3040
3041// If an app is not responding to a motion event, gesture monitors should continue to receive
3042// new motion events
3043TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
3044 FakeMonitorReceiver monitor =
3045 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
3046 true /*isGestureMonitor*/);
3047
3048 tapOnWindow();
3049 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3050 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3051
3052 mWindow->consumeMotionDown();
3053 // Stuck on the ACTION_UP
3054 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3055 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr, mWindow->getToken());
3056
3057 // New tap will go to the gesture monitor, but not to the window
3058 tapOnWindow();
3059 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3060 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3061
3062 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
3063 mDispatcher->waitForIdle();
3064 mWindow->assertNoEvents();
3065 monitor.assertNoEvents();
3066}
3067
3068// If a window is unresponsive, then you get anr. if the window later catches up and starts to
3069// process events, you don't get an anr. When the window later becomes unresponsive again, you
3070// get an ANR again.
3071// 1. tap -> block on ACTION_UP -> receive ANR
3072// 2. consume all pending events (= queue becomes healthy again)
3073// 3. tap again -> block on ACTION_UP again -> receive ANR second time
3074TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
3075 tapOnWindow();
3076
3077 mWindow->consumeMotionDown();
3078 // Block on ACTION_UP
3079 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3080 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
3081 mWindow->consumeMotionUp(); // Now the connection should be healthy again
3082 mDispatcher->waitForIdle();
3083 mWindow->assertNoEvents();
3084
3085 tapOnWindow();
3086 mWindow->consumeMotionDown();
3087 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
3088 mWindow->consumeMotionUp();
3089
3090 mDispatcher->waitForIdle();
3091 mWindow->assertNoEvents();
3092}
3093
3094// If the policy tells us to raise ANR again after some time, ensure that the timeout extension
3095// is honored
3096TEST_F(InputDispatcherSingleWindowAnr, Policy_CanExtendTimeout) {
3097 const std::chrono::duration timeout = 5ms;
3098 mFakePolicy->setAnrTimeout(timeout);
3099
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003100 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003101 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3102 WINDOW_LOCATION));
3103
3104 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3105 mFakePolicy->assertNotifyAnrWasCalled(windowTimeout, nullptr /*application*/,
3106 mWindow->getToken());
3107
3108 // Since the policy wanted to extend ANR, make sure it is called again after the extension
3109 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
3110 mFakePolicy->setAnrTimeout(0ms);
3111 std::this_thread::sleep_for(windowTimeout);
3112 // We are not checking if ANR has been called, because it may have been called again by the
3113 // time we set the timeout to 0
3114
3115 // When the policy finally says stop, we should get ACTION_CANCEL
3116 mWindow->consumeMotionDown();
3117 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
3118 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3119 mWindow->assertNoEvents();
3120}
3121
3122/**
3123 * If a window is processing a motion event, and then a key event comes in, the key event should
3124 * not to to the focused window until the motion is processed.
3125 *
3126 * Warning!!!
3127 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
3128 * and the injection timeout that we specify when injecting the key.
3129 * We must have the injection timeout (10ms) be smaller than
3130 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
3131 *
3132 * If that value changes, this test should also change.
3133 */
3134TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
3135 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
3136 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3137
3138 tapOnWindow();
3139 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
3140 ASSERT_TRUE(downSequenceNum);
3141 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
3142 ASSERT_TRUE(upSequenceNum);
3143 // Don't finish the events yet, and send a key
3144 // Injection will "succeed" because we will eventually give up and send the key to the focused
3145 // window even if motions are still being processed. But because the injection timeout is short,
3146 // we will receive INJECTION_TIMED_OUT as the result.
3147
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003148 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003149 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003150 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3151 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003152 // Key will not be sent to the window, yet, because the window is still processing events
3153 // and the key remains pending, waiting for the touch events to be processed
3154 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
3155 ASSERT_FALSE(keySequenceNum);
3156
3157 std::this_thread::sleep_for(500ms);
3158 // if we wait long enough though, dispatcher will give up, and still send the key
3159 // to the focused window, even though we have not yet finished the motion event
3160 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3161 mWindow->finishEvent(*downSequenceNum);
3162 mWindow->finishEvent(*upSequenceNum);
3163}
3164
3165/**
3166 * If a window is processing a motion event, and then a key event comes in, the key event should
3167 * not go to the focused window until the motion is processed.
3168 * If then a new motion comes in, then the pending key event should be going to the currently
3169 * focused window right away.
3170 */
3171TEST_F(InputDispatcherSingleWindowAnr,
3172 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
3173 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
3174 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3175
3176 tapOnWindow();
3177 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
3178 ASSERT_TRUE(downSequenceNum);
3179 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
3180 ASSERT_TRUE(upSequenceNum);
3181 // Don't finish the events yet, and send a key
3182 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003184 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003185 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003186 // At this point, key is still pending, and should not be sent to the application yet.
3187 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
3188 ASSERT_FALSE(keySequenceNum);
3189
3190 // Now tap down again. It should cause the pending key to go to the focused window right away.
3191 tapOnWindow();
3192 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
3193 // the other events yet. We can finish events in any order.
3194 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
3195 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
3196 mWindow->consumeMotionDown();
3197 mWindow->consumeMotionUp();
3198 mWindow->assertNoEvents();
3199}
3200
3201class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
3202 virtual void SetUp() override {
3203 InputDispatcherTest::SetUp();
3204
Chris Yea209fde2020-07-22 13:54:51 -07003205 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003206 mApplication->setDispatchingTimeout(10ms);
3207 mUnfocusedWindow =
3208 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
3209 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
3210 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3211 // window.
3212 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Michael Wright44753b12020-07-08 13:48:11 +01003213 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3214 InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
3215 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003216
3217 mFocusedWindow =
3218 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05003219 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003220 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01003221 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3222 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003223
3224 // Set focused application.
3225 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07003226 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003227
3228 // Expect one focus window exist in display.
3229 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003230 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003231 mFocusedWindow->consumeFocusEvent(true);
3232 }
3233
3234 virtual void TearDown() override {
3235 InputDispatcherTest::TearDown();
3236
3237 mUnfocusedWindow.clear();
3238 mFocusedWindow.clear();
3239 }
3240
3241protected:
Chris Yea209fde2020-07-22 13:54:51 -07003242 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003243 sp<FakeWindowHandle> mUnfocusedWindow;
3244 sp<FakeWindowHandle> mFocusedWindow;
3245 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
3246 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
3247 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
3248
3249 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
3250
3251 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
3252
3253private:
3254 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003255 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003256 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3257 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003259 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3260 location));
3261 }
3262};
3263
3264// If we have 2 windows that are both unresponsive, the one with the shortest timeout
3265// should be ANR'd first.
3266TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003268 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3269 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003270 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003271 mFocusedWindow->consumeMotionDown();
3272 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3273 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3274 // We consumed all events, so no ANR
3275 ASSERT_TRUE(mDispatcher->waitForIdle());
3276 mFakePolicy->assertNotifyAnrWasNotCalled();
3277
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003279 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3280 FOCUSED_WINDOW_LOCATION));
3281 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
3282 ASSERT_TRUE(unfocusedSequenceNum);
3283 std::optional<uint32_t> focusedSequenceNum = mFocusedWindow->receiveEvent();
3284 ASSERT_TRUE(focusedSequenceNum);
3285
3286 const std::chrono::duration timeout =
3287 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3288 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
3289 mFocusedWindow->getToken());
3290
3291 mFocusedWindow->finishEvent(*focusedSequenceNum);
3292 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
3293 ASSERT_TRUE(mDispatcher->waitForIdle());
3294}
3295
3296// If we have 2 windows with identical timeouts that are both unresponsive,
3297// it doesn't matter which order they should have ANR.
3298// But we should receive ANR for both.
3299TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
3300 // Set the timeout for unfocused window to match the focused window
3301 mUnfocusedWindow->setDispatchingTimeout(10ms);
3302 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3303
3304 tapOnFocusedWindow();
3305 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Chris Yea209fde2020-07-22 13:54:51 -07003306 std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> anrData1 =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003307 mFakePolicy->getNotifyAnrData(10ms);
Chris Yea209fde2020-07-22 13:54:51 -07003308 std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> anrData2 =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003309 mFakePolicy->getNotifyAnrData(0ms);
3310
3311 // We don't know which window will ANR first. But both of them should happen eventually.
3312 ASSERT_TRUE(mFocusedWindow->getToken() == anrData1.second ||
3313 mFocusedWindow->getToken() == anrData2.second);
3314 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrData1.second ||
3315 mUnfocusedWindow->getToken() == anrData2.second);
3316
3317 ASSERT_TRUE(mDispatcher->waitForIdle());
3318 mFakePolicy->assertNotifyAnrWasNotCalled();
3319}
3320
3321// If a window is already not responding, the second tap on the same window should be ignored.
3322// We should also log an error to account for the dropped event (not tested here).
3323// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
3324TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
3325 tapOnFocusedWindow();
3326 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3327 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3328 // Receive the events, but don't respond
3329 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
3330 ASSERT_TRUE(downEventSequenceNum);
3331 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
3332 ASSERT_TRUE(upEventSequenceNum);
3333 const std::chrono::duration timeout =
3334 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3335 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
3336 mFocusedWindow->getToken());
3337
3338 // Tap once again
3339 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003340 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003341 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3342 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003343 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003344 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3345 FOCUSED_WINDOW_LOCATION));
3346 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
3347 // valid touch target
3348 mUnfocusedWindow->assertNoEvents();
3349
3350 // Consume the first tap
3351 mFocusedWindow->finishEvent(*downEventSequenceNum);
3352 mFocusedWindow->finishEvent(*upEventSequenceNum);
3353 ASSERT_TRUE(mDispatcher->waitForIdle());
3354 // The second tap did not go to the focused window
3355 mFocusedWindow->assertNoEvents();
3356 // should not have another ANR after the window just became healthy again
3357 mFakePolicy->assertNotifyAnrWasNotCalled();
3358}
3359
3360// If you tap outside of all windows, there will not be ANR
3361TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003362 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003363 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3364 LOCATION_OUTSIDE_ALL_WINDOWS));
3365 ASSERT_TRUE(mDispatcher->waitForIdle());
3366 mFakePolicy->assertNotifyAnrWasNotCalled();
3367}
3368
3369// Since the focused window is paused, tapping on it should not produce any events
3370TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
3371 mFocusedWindow->setPaused(true);
3372 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3373
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003374 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003375 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3376 FOCUSED_WINDOW_LOCATION));
3377
3378 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
3379 ASSERT_TRUE(mDispatcher->waitForIdle());
3380 // Should not ANR because the window is paused, and touches shouldn't go to it
3381 mFakePolicy->assertNotifyAnrWasNotCalled();
3382
3383 mFocusedWindow->assertNoEvents();
3384 mUnfocusedWindow->assertNoEvents();
3385}
3386
3387/**
3388 * If a window is processing a motion event, and then a key event comes in, the key event should
3389 * not to to the focused window until the motion is processed.
3390 * If a different window becomes focused at this time, the key should go to that window instead.
3391 *
3392 * Warning!!!
3393 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
3394 * and the injection timeout that we specify when injecting the key.
3395 * We must have the injection timeout (10ms) be smaller than
3396 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
3397 *
3398 * If that value changes, this test should also change.
3399 */
3400TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
3401 // Set a long ANR timeout to prevent it from triggering
3402 mFocusedWindow->setDispatchingTimeout(2s);
3403 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3404
3405 tapOnUnfocusedWindow();
3406 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
3407 ASSERT_TRUE(downSequenceNum);
3408 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
3409 ASSERT_TRUE(upSequenceNum);
3410 // Don't finish the events yet, and send a key
3411 // Injection will succeed because we will eventually give up and send the key to the focused
3412 // window even if motions are still being processed.
3413
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003414 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003415 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003416 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
3417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003418 // Key will not be sent to the window, yet, because the window is still processing events
3419 // and the key remains pending, waiting for the touch events to be processed
3420 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
3421 ASSERT_FALSE(keySequenceNum);
3422
3423 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07003424 mFocusedWindow->setFocusable(false);
3425 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003426 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003427 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003428
3429 // Focus events should precede the key events
3430 mUnfocusedWindow->consumeFocusEvent(true);
3431 mFocusedWindow->consumeFocusEvent(false);
3432
3433 // Finish the tap events, which should unblock dispatcher
3434 mUnfocusedWindow->finishEvent(*downSequenceNum);
3435 mUnfocusedWindow->finishEvent(*upSequenceNum);
3436
3437 // Now that all queues are cleared and no backlog in the connections, the key event
3438 // can finally go to the newly focused "mUnfocusedWindow".
3439 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3440 mFocusedWindow->assertNoEvents();
3441 mUnfocusedWindow->assertNoEvents();
3442}
3443
3444// When the touch stream is split across 2 windows, and one of them does not respond,
3445// then ANR should be raised and the touch should be canceled for the unresponsive window.
3446// The other window should not be affected by that.
3447TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
3448 // Touch Window 1
3449 NotifyMotionArgs motionArgs =
3450 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3451 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
3452 mDispatcher->notifyMotion(&motionArgs);
3453 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3454 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3455
3456 // Touch Window 2
3457 int32_t actionPointerDown =
3458 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3459
3460 motionArgs =
3461 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3462 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
3463 mDispatcher->notifyMotion(&motionArgs);
3464
3465 const std::chrono::duration timeout =
3466 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3467 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
3468 mFocusedWindow->getToken());
3469
3470 mUnfocusedWindow->consumeMotionDown();
3471 mFocusedWindow->consumeMotionDown();
3472 // Focused window may or may not receive ACTION_MOVE
3473 // But it should definitely receive ACTION_CANCEL due to the ANR
3474 InputEvent* event;
3475 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
3476 ASSERT_TRUE(moveOrCancelSequenceNum);
3477 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
3478 ASSERT_NE(nullptr, event);
3479 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
3480 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
3481 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
3482 mFocusedWindow->consumeMotionCancel();
3483 } else {
3484 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
3485 }
3486
3487 ASSERT_TRUE(mDispatcher->waitForIdle());
3488 mUnfocusedWindow->assertNoEvents();
3489 mFocusedWindow->assertNoEvents();
3490}
3491
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003492/**
3493 * If we have no focused window, and a key comes in, we start the ANR timer.
3494 * The focused application should add a focused window before the timer runs out to prevent ANR.
3495 *
3496 * If the user touches another application during this time, the key should be dropped.
3497 * Next, if a new focused window comes in, without toggling the focused application,
3498 * then no ANR should occur.
3499 *
3500 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
3501 * but in some cases the policy may not update the focused application.
3502 */
3503TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
3504 std::shared_ptr<FakeApplicationHandle> focusedApplication =
3505 std::make_shared<FakeApplicationHandle>();
3506 focusedApplication->setDispatchingTimeout(60ms);
3507 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
3508 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
3509 mFocusedWindow->setFocusable(false);
3510
3511 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3512 mFocusedWindow->consumeFocusEvent(false);
3513
3514 // Send a key. The ANR timer should start because there is no focused window.
3515 // 'focusedApplication' will get blamed if this timer completes.
3516 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003517 InputEventInjectionResult result =
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003518 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003519 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
3520 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003521
3522 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
3523 // then the injected touches won't cause the focused event to get dropped.
3524 // The dispatcher only checks for whether the queue should be pruned upon queueing.
3525 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
3526 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
3527 // For this test, it means that the key would get delivered to the window once it becomes
3528 // focused.
3529 std::this_thread::sleep_for(10ms);
3530
3531 // Touch unfocused window. This should force the pending key to get dropped.
3532 NotifyMotionArgs motionArgs =
3533 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3534 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
3535 mDispatcher->notifyMotion(&motionArgs);
3536
3537 // We do not consume the motion right away, because that would require dispatcher to first
3538 // process (== drop) the key event, and by that time, ANR will be raised.
3539 // Set the focused window first.
3540 mFocusedWindow->setFocusable(true);
3541 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3542 setFocusedWindow(mFocusedWindow);
3543 mFocusedWindow->consumeFocusEvent(true);
3544 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
3545 // to another application. This could be a bug / behaviour in the policy.
3546
3547 mUnfocusedWindow->consumeMotionDown();
3548
3549 ASSERT_TRUE(mDispatcher->waitForIdle());
3550 // Should not ANR because we actually have a focused window. It was just added too slowly.
3551 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
3552}
3553
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05003554// These tests ensure we cannot send touch events to a window that's positioned behind a window
3555// that has feature NO_INPUT_CHANNEL.
3556// Layout:
3557// Top (closest to user)
3558// mNoInputWindow (above all windows)
3559// mBottomWindow
3560// Bottom (furthest from user)
3561class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
3562 virtual void SetUp() override {
3563 InputDispatcherTest::SetUp();
3564
3565 mApplication = std::make_shared<FakeApplicationHandle>();
3566 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
3567 "Window without input channel", ADISPLAY_ID_DEFAULT,
3568 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
3569
3570 mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
3571 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
3572 // It's perfectly valid for this window to not have an associated input channel
3573
3574 mBottomWindow = new FakeWindowHandle(mApplication, mDispatcher, "Bottom window",
3575 ADISPLAY_ID_DEFAULT);
3576 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
3577
3578 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
3579 }
3580
3581protected:
3582 std::shared_ptr<FakeApplicationHandle> mApplication;
3583 sp<FakeWindowHandle> mNoInputWindow;
3584 sp<FakeWindowHandle> mBottomWindow;
3585};
3586
3587TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
3588 PointF touchedPoint = {10, 10};
3589
3590 NotifyMotionArgs motionArgs =
3591 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3592 ADISPLAY_ID_DEFAULT, {touchedPoint});
3593 mDispatcher->notifyMotion(&motionArgs);
3594
3595 mNoInputWindow->assertNoEvents();
3596 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
3597 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
3598 // and therefore should prevent mBottomWindow from receiving touches
3599 mBottomWindow->assertNoEvents();
3600}
3601
3602/**
3603 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
3604 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
3605 */
3606TEST_F(InputDispatcherMultiWindowOcclusionTests,
3607 NoInputChannelFeature_DropsTouchesWithValidChannel) {
3608 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
3609 "Window with input channel and NO_INPUT_CHANNEL",
3610 ADISPLAY_ID_DEFAULT);
3611
3612 mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
3613 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
3614 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
3615
3616 PointF touchedPoint = {10, 10};
3617
3618 NotifyMotionArgs motionArgs =
3619 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3620 ADISPLAY_ID_DEFAULT, {touchedPoint});
3621 mDispatcher->notifyMotion(&motionArgs);
3622
3623 mNoInputWindow->assertNoEvents();
3624 mBottomWindow->assertNoEvents();
3625}
3626
Vishnu Nair958da932020-08-21 17:12:37 -07003627class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
3628protected:
3629 std::shared_ptr<FakeApplicationHandle> mApp;
3630 sp<FakeWindowHandle> mWindow;
3631 sp<FakeWindowHandle> mMirror;
3632
3633 virtual void SetUp() override {
3634 InputDispatcherTest::SetUp();
3635 mApp = std::make_shared<FakeApplicationHandle>();
3636 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3637 mMirror = new FakeWindowHandle(mApp, mDispatcher, "TestWindowMirror", ADISPLAY_ID_DEFAULT,
3638 mWindow->getToken());
3639 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
3640 mWindow->setFocusable(true);
3641 mMirror->setFocusable(true);
3642 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3643 }
3644};
3645
3646TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
3647 // Request focus on a mirrored window
3648 setFocusedWindow(mMirror);
3649
3650 // window gets focused
3651 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3653 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003654 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
3655}
3656
3657// A focused & mirrored window remains focused only if the window and its mirror are both
3658// focusable.
3659TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
3660 setFocusedWindow(mMirror);
3661
3662 // window gets focused
3663 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3665 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003666 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3668 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003669 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3670
3671 mMirror->setFocusable(false);
3672 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3673
3674 // window loses focus since one of the windows associated with the token in not focusable
3675 mWindow->consumeFocusEvent(false);
3676
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003677 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3678 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003679 mWindow->assertNoEvents();
3680}
3681
3682// A focused & mirrored window remains focused until the window and its mirror both become
3683// invisible.
3684TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
3685 setFocusedWindow(mMirror);
3686
3687 // window gets focused
3688 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3690 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003691 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3693 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003694 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3695
3696 mMirror->setVisible(false);
3697 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3698
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3700 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003701 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3703 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003704 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3705
3706 mWindow->setVisible(false);
3707 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3708
3709 // window loses focus only after all windows associated with the token become invisible.
3710 mWindow->consumeFocusEvent(false);
3711
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003712 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3713 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003714 mWindow->assertNoEvents();
3715}
3716
3717// A focused & mirrored window remains focused until both windows are removed.
3718TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
3719 setFocusedWindow(mMirror);
3720
3721 // window gets focused
3722 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3724 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003725 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3727 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003728 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3729
3730 // single window is removed but the window token remains focused
3731 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
3732
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3734 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003735 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3737 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003738 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3739
3740 // Both windows are removed
3741 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3742 mWindow->consumeFocusEvent(false);
3743
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003744 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3745 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003746 mWindow->assertNoEvents();
3747}
3748
3749// Focus request can be pending until one window becomes visible.
3750TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
3751 // Request focus on an invisible mirror.
3752 mWindow->setVisible(false);
3753 mMirror->setVisible(false);
3754 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3755 setFocusedWindow(mMirror);
3756
3757 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07003759 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003760 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07003761
3762 mMirror->setVisible(true);
3763 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3764
3765 // window gets focused
3766 mWindow->consumeFocusEvent(true);
3767 // window gets the pending key event
3768 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3769}
Garfield Tane84e6f92019-08-29 17:28:41 -07003770} // namespace android::inputdispatcher