blob: 0d58aaf6edb6a1056637632b3fca1af1c6be3658 [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>
Michael Wrightd02c5b62014-02-10 15:10:22 -080022#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100023#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080024#include <linux/input.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100025
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:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100074 virtual ~FakeInputDispatcherPolicy() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -080075
76public:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100077 FakeInputDispatcherPolicy() {}
Jackal Guof9696682018-10-05 12:23:23 +080078
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080079 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080080 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
81 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080082 }
83
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080084 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080085 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
86 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080087 }
88
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070089 void assertFilterInputEventWasNotCalled() {
90 std::scoped_lock lock(mLock);
91 ASSERT_EQ(nullptr, mFilteredEvent);
92 }
Michael Wrightd02c5b62014-02-10 15:10:22 -080093
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080094 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070095 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080096 ASSERT_TRUE(mConfigurationChangedTime)
97 << "Timed out waiting for configuration changed call";
98 ASSERT_EQ(*mConfigurationChangedTime, when);
99 mConfigurationChangedTime = std::nullopt;
100 }
101
102 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700103 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800104 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800105 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800106 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
107 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
108 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
109 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
110 mLastNotifySwitch = std::nullopt;
111 }
112
chaviwfd6d3512019-03-25 13:23:49 -0700113 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700114 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800115 ASSERT_EQ(touchedToken, mOnPointerDownToken);
116 mOnPointerDownToken.clear();
117 }
118
119 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700120 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800121 ASSERT_TRUE(mOnPointerDownToken == nullptr)
122 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700123 }
124
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700125 // This function must be called soon after the expected ANR timer starts,
126 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500127 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700128 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500129 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
130 std::shared_ptr<InputApplicationHandle> application;
131 { // acquire lock
132 std::unique_lock lock(mLock);
133 android::base::ScopedLockAssertion assumeLocked(mLock);
134 ASSERT_NO_FATAL_FAILURE(
135 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
136 } // release lock
137 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700138 }
139
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500140 void assertNotifyConnectionUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
141 const sp<IBinder>& expectedConnectionToken) {
142 sp<IBinder> connectionToken = getUnresponsiveConnectionToken(timeout);
143 ASSERT_EQ(expectedConnectionToken, connectionToken);
144 }
145
146 void assertNotifyConnectionResponsiveWasCalled(const sp<IBinder>& expectedConnectionToken) {
147 sp<IBinder> connectionToken = getResponsiveConnectionToken();
148 ASSERT_EQ(expectedConnectionToken, connectionToken);
149 }
150
151 sp<IBinder> getUnresponsiveConnectionToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700152 std::unique_lock lock(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700153 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500154 return getAnrTokenLockedInterruptible(timeout, mAnrConnectionTokens, lock);
155 }
156
157 sp<IBinder> getResponsiveConnectionToken() {
158 std::unique_lock lock(mLock);
159 android::base::ScopedLockAssertion assumeLocked(mLock);
160 return getAnrTokenLockedInterruptible(0s, mResponsiveConnectionTokens, lock);
161 }
162
163 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
164 // for a specific container to become non-empty. When the container is non-empty, return the
165 // first entry from the container and erase it.
166 template <class T>
167 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
168 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
169 const std::chrono::time_point start = std::chrono::steady_clock::now();
170 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700171
172 // If there is an ANR, Dispatcher won't be idle because there are still events
173 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
174 // before checking if ANR was called.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500175 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
176 // to provide it some time to act. 100ms seems reasonable.
177 mNotifyAnr.wait_for(lock, timeToWait,
178 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700179 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500180 if (storage.empty()) {
181 ADD_FAILURE() << "Did not receive the ANR callback";
182 return nullptr;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700183 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700184 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
185 // the dispatcher started counting before this function was called
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700186 if (std::chrono::abs(timeout - waited) > 100ms) {
187 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
188 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
189 << "ms, but waited "
190 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
191 << "ms instead";
192 }
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500193 T token = storage.front();
194 storage.pop();
195 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700196 }
197
198 void assertNotifyAnrWasNotCalled() {
199 std::scoped_lock lock(mLock);
200 ASSERT_TRUE(mAnrApplications.empty());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500201 ASSERT_TRUE(mAnrConnectionTokens.empty());
202 ASSERT_TRUE(mResponsiveConnectionTokens.empty())
203 << "ANR was not called, but please also consume the 'connection is responsive' "
204 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700205 }
206
Garfield Tan1c7bc862020-01-28 13:24:04 -0800207 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
208 mConfig.keyRepeatTimeout = timeout;
209 mConfig.keyRepeatDelay = delay;
210 }
211
Michael Wrightd02c5b62014-02-10 15:10:22 -0800212private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700213 std::mutex mLock;
214 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
215 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
216 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
217 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800218
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700219 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700220 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500221 std::queue<sp<IBinder>> mAnrConnectionTokens GUARDED_BY(mLock);
222 std::queue<sp<IBinder>> mResponsiveConnectionTokens GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700223 std::condition_variable mNotifyAnr;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700224
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600225 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700226 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800227 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800228 }
229
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500230 void notifyConnectionUnresponsive(const sp<IBinder>& connectionToken,
231 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700232 std::scoped_lock lock(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500233 mAnrConnectionTokens.push(connectionToken);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700234 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500235 }
236
237 void notifyConnectionResponsive(const sp<IBinder>& connectionToken) override {
238 std::scoped_lock lock(mLock);
239 mResponsiveConnectionTokens.push(connectionToken);
240 mNotifyAnr.notify_all();
241 }
242
243 void notifyNoFocusedWindowAnr(
244 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
245 std::scoped_lock lock(mLock);
246 mAnrApplications.push(applicationHandle);
247 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800248 }
249
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600250 void notifyInputChannelBroken(const sp<IBinder>&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800251
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600252 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700253
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600254 void notifyUntrustedTouch(const std::string& obscuringPackage) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000255
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600256 void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800257 *outConfig = mConfig;
258 }
259
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600260 bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700261 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800262 switch (inputEvent->getType()) {
263 case AINPUT_EVENT_TYPE_KEY: {
264 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800265 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800266 break;
267 }
268
269 case AINPUT_EVENT_TYPE_MOTION: {
270 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800271 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800272 break;
273 }
274 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800275 return true;
276 }
277
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600278 void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800279
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600280 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800281
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600282 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800283 return 0;
284 }
285
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600286 bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800287 return false;
288 }
289
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600290 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
291 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700292 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800293 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
294 * essentially a passthrough for notifySwitch.
295 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800296 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800297 }
298
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600299 void pokeUserActivity(nsecs_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800300
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600301 bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override { return false; }
Jackal Guof9696682018-10-05 12:23:23 +0800302
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600303 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700304 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700305 mOnPointerDownToken = newToken;
306 }
307
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800308 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
309 int32_t displayId) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700310 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800311 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
312 ASSERT_EQ(mFilteredEvent->getType(), type);
313
314 if (type == AINPUT_EVENT_TYPE_KEY) {
315 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
316 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
317 EXPECT_EQ(keyEvent.getAction(), action);
318 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
319 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
320 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
321 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
322 EXPECT_EQ(motionEvent.getAction(), action);
323 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
324 } else {
325 FAIL() << "Unknown type: " << type;
326 }
327
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800328 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800329 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800330};
331
Michael Wrightd02c5b62014-02-10 15:10:22 -0800332// --- InputDispatcherTest ---
333
334class InputDispatcherTest : public testing::Test {
335protected:
336 sp<FakeInputDispatcherPolicy> mFakePolicy;
337 sp<InputDispatcher> mDispatcher;
338
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700339 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800340 mFakePolicy = new FakeInputDispatcherPolicy();
341 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800342 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000343 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700344 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800345 }
346
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700347 virtual void TearDown() override {
348 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800349 mFakePolicy.clear();
350 mDispatcher.clear();
351 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700352
353 /**
354 * Used for debugging when writing the test
355 */
356 void dumpDispatcherState() {
357 std::string dump;
358 mDispatcher->dump(dump);
359 std::stringstream ss(dump);
360 std::string to;
361
362 while (std::getline(ss, to, '\n')) {
363 ALOGE("%s", to.c_str());
364 }
365 }
Vishnu Nair958da932020-08-21 17:12:37 -0700366
367 void setFocusedWindow(const sp<InputWindowHandle>& window,
368 const sp<InputWindowHandle>& focusedWindow = nullptr) {
369 FocusRequest request;
370 request.token = window->getToken();
371 if (focusedWindow) {
372 request.focusedToken = focusedWindow->getToken();
373 }
374 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
375 request.displayId = window->getInfo()->displayId;
376 mDispatcher->setFocusedWindow(request);
377 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800378};
379
Michael Wrightd02c5b62014-02-10 15:10:22 -0800380TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
381 KeyEvent event;
382
383 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800384 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
385 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600386 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
387 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800388 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700389 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800390 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800391 << "Should reject key events with undefined action.";
392
393 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800394 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
395 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600396 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800397 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700398 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800399 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800400 << "Should reject key events with ACTION_MULTIPLE.";
401}
402
403TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
404 MotionEvent event;
405 PointerProperties pointerProperties[MAX_POINTERS + 1];
406 PointerCoords pointerCoords[MAX_POINTERS + 1];
407 for (int i = 0; i <= MAX_POINTERS; i++) {
408 pointerProperties[i].clear();
409 pointerProperties[i].id = i;
410 pointerCoords[i].clear();
411 }
412
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800413 // Some constants commonly used below
414 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
415 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
416 constexpr int32_t metaState = AMETA_NONE;
417 constexpr MotionClassification classification = MotionClassification::NONE;
418
chaviw9eaa22c2020-07-01 16:21:27 -0700419 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800420 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800421 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700422 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
423 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600424 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700425 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800426 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700427 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800428 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800429 << "Should reject motion events with undefined action.";
430
431 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800432 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700433 AMOTION_EVENT_ACTION_POINTER_DOWN |
434 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700435 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
436 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
437 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
438 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800439 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700440 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800441 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800442 << "Should reject motion events with pointer down index too large.";
443
Garfield Tanfbe732e2020-01-24 11:26:14 -0800444 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700445 AMOTION_EVENT_ACTION_POINTER_DOWN |
446 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700447 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
448 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
449 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
450 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800451 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700452 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800453 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800454 << "Should reject motion events with pointer down index too small.";
455
456 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800457 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700458 AMOTION_EVENT_ACTION_POINTER_UP |
459 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700460 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
461 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
462 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
463 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800464 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700465 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800466 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800467 << "Should reject motion events with pointer up index too large.";
468
Garfield Tanfbe732e2020-01-24 11:26:14 -0800469 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700470 AMOTION_EVENT_ACTION_POINTER_UP |
471 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700472 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
473 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
474 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
475 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800476 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700477 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800478 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800479 << "Should reject motion events with pointer up index too small.";
480
481 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800482 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
483 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700484 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
485 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700486 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800487 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700488 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800489 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800490 << "Should reject motion events with 0 pointers.";
491
Garfield Tanfbe732e2020-01-24 11:26:14 -0800492 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
493 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700494 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
495 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700496 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800497 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700498 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800499 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800500 << "Should reject motion events with more than MAX_POINTERS pointers.";
501
502 // Rejects motion events with invalid pointer ids.
503 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800504 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
505 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700506 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
507 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700508 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800509 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700510 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800511 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800512 << "Should reject motion events with pointer ids less than 0.";
513
514 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800515 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
516 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700517 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
518 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700519 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800520 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700521 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800522 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800523 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
524
525 // Rejects motion events with duplicate pointer ids.
526 pointerProperties[0].id = 1;
527 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800528 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
529 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700530 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
531 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700532 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800533 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700534 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800535 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800536 << "Should reject motion events with duplicate pointer ids.";
537}
538
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800539/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
540
541TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
542 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800543 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800544 mDispatcher->notifyConfigurationChanged(&args);
545 ASSERT_TRUE(mDispatcher->waitForIdle());
546
547 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
548}
549
550TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800551 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
552 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800553 mDispatcher->notifySwitch(&args);
554
555 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
556 args.policyFlags |= POLICY_FLAG_TRUSTED;
557 mFakePolicy->assertNotifySwitchWasCalled(args);
558}
559
Arthur Hungb92218b2018-08-14 12:00:21 +0800560// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700561static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700562static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
Arthur Hungb92218b2018-08-14 12:00:21 +0800563
564class FakeApplicationHandle : public InputApplicationHandle {
565public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700566 FakeApplicationHandle() {
567 mInfo.name = "Fake Application";
568 mInfo.token = new BBinder();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500569 mInfo.dispatchingTimeoutMillis =
570 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700571 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800572 virtual ~FakeApplicationHandle() {}
573
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000574 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700575
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500576 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
577 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700578 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800579};
580
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800581class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800582public:
Garfield Tan15601662020-09-22 15:32:38 -0700583 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800584 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700585 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800586 }
587
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800588 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700589 InputEvent* event;
590 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
591 if (!consumeSeq) {
592 return nullptr;
593 }
594 finishEvent(*consumeSeq);
595 return event;
596 }
597
598 /**
599 * Receive an event without acknowledging it.
600 * Return the sequence number that could later be used to send finished signal.
601 */
602 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800603 uint32_t consumeSeq;
604 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800605
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800606 std::chrono::time_point start = std::chrono::steady_clock::now();
607 status_t status = WOULD_BLOCK;
608 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800609 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800610 &event);
611 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
612 if (elapsed > 100ms) {
613 break;
614 }
615 }
616
617 if (status == WOULD_BLOCK) {
618 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700619 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800620 }
621
622 if (status != OK) {
623 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700624 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800625 }
626 if (event == nullptr) {
627 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700628 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800629 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700630 if (outEvent != nullptr) {
631 *outEvent = event;
632 }
633 return consumeSeq;
634 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800635
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700636 /**
637 * To be used together with "receiveEvent" to complete the consumption of an event.
638 */
639 void finishEvent(uint32_t consumeSeq) {
640 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
641 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800642 }
643
644 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
645 int32_t expectedFlags) {
646 InputEvent* event = consume();
647
648 ASSERT_NE(nullptr, event) << mName.c_str()
649 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800650 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700651 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800652 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800653
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800654 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800655
Tiger Huang8664f8c2018-10-11 19:14:35 +0800656 switch (expectedEventType) {
657 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800658 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
659 EXPECT_EQ(expectedAction, keyEvent.getAction());
660 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800661 break;
662 }
663 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800664 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
665 EXPECT_EQ(expectedAction, motionEvent.getAction());
666 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800667 break;
668 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100669 case AINPUT_EVENT_TYPE_FOCUS: {
670 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
671 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800672 default: {
673 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
674 }
675 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800676 }
677
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100678 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
679 InputEvent* event = consume();
680 ASSERT_NE(nullptr, event) << mName.c_str()
681 << ": consumer should have returned non-NULL event.";
682 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
683 << "Got " << inputEventTypeToString(event->getType())
684 << " event instead of FOCUS event";
685
686 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
687 << mName.c_str() << ": event displayId should always be NONE.";
688
689 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
690 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
691 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
692 }
693
chaviwd1c23182019-12-20 18:44:56 -0800694 void assertNoEvents() {
695 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700696 if (event == nullptr) {
697 return;
698 }
699 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
700 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
701 ADD_FAILURE() << "Received key event "
702 << KeyEvent::actionToString(keyEvent.getAction());
703 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
704 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
705 ADD_FAILURE() << "Received motion event "
706 << MotionEvent::actionToString(motionEvent.getAction());
707 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
708 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
709 ADD_FAILURE() << "Received focus event, hasFocus = "
710 << (focusEvent.getHasFocus() ? "true" : "false");
711 }
712 FAIL() << mName.c_str()
713 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800714 }
715
716 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
717
718protected:
719 std::unique_ptr<InputConsumer> mConsumer;
720 PreallocatedInputEventFactory mEventFactory;
721
722 std::string mName;
723};
724
725class FakeWindowHandle : public InputWindowHandle {
726public:
727 static const int32_t WIDTH = 600;
728 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800729
Chris Yea209fde2020-07-22 13:54:51 -0700730 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
chaviwd1c23182019-12-20 18:44:56 -0800731 const sp<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500732 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -0800733 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500734 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -0700735 base::Result<std::unique_ptr<InputChannel>> channel =
736 dispatcher->createInputChannel(name);
737 token = (*channel)->getConnectionToken();
738 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -0800739 }
740
741 inputApplicationHandle->updateInfo();
742 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
743
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500744 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700745 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800746 mInfo.name = name;
Michael Wright44753b12020-07-08 13:48:11 +0100747 mInfo.type = InputWindowInfo::Type::APPLICATION;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500748 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
chaviwd1c23182019-12-20 18:44:56 -0800749 mInfo.frameLeft = 0;
750 mInfo.frameTop = 0;
751 mInfo.frameRight = WIDTH;
752 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -0700753 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -0800754 mInfo.globalScaleFactor = 1.0;
755 mInfo.touchableRegion.clear();
756 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
757 mInfo.visible = true;
Vishnu Nair47074b82020-08-14 11:54:47 -0700758 mInfo.focusable = false;
chaviwd1c23182019-12-20 18:44:56 -0800759 mInfo.hasWallpaper = false;
760 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800761 mInfo.ownerPid = INJECTOR_PID;
762 mInfo.ownerUid = INJECTOR_UID;
chaviwd1c23182019-12-20 18:44:56 -0800763 mInfo.displayId = displayId;
764 }
765
766 virtual bool updateInfo() { return true; }
767
Vishnu Nair47074b82020-08-14 11:54:47 -0700768 void setFocusable(bool focusable) { mInfo.focusable = focusable; }
chaviwd1c23182019-12-20 18:44:56 -0800769
Vishnu Nair958da932020-08-21 17:12:37 -0700770 void setVisible(bool visible) { mInfo.visible = visible; }
771
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700772 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500773 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700774 }
775
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700776 void setPaused(bool paused) { mInfo.paused = paused; }
777
chaviwd1c23182019-12-20 18:44:56 -0800778 void setFrame(const Rect& frame) {
779 mInfo.frameLeft = frame.left;
780 mInfo.frameTop = frame.top;
781 mInfo.frameRight = frame.right;
782 mInfo.frameBottom = frame.bottom;
chaviw1ff3d1e2020-07-01 15:53:47 -0700783 mInfo.transform.set(frame.left, frame.top);
chaviwd1c23182019-12-20 18:44:56 -0800784 mInfo.touchableRegion.clear();
785 mInfo.addTouchableRegion(frame);
786 }
787
Michael Wright44753b12020-07-08 13:48:11 +0100788 void setFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags = flags; }
chaviwd1c23182019-12-20 18:44:56 -0800789
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500790 void setInputFeatures(InputWindowInfo::Feature features) { mInfo.inputFeatures = features; }
791
chaviw9eaa22c2020-07-01 16:21:27 -0700792 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
793 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
794 }
795
796 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -0700797
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800798 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
799 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
800 expectedFlags);
801 }
802
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700803 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
804 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
805 }
806
Svet Ganov5d3bc372020-01-26 23:11:07 -0800807 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000808 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800809 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
810 expectedFlags);
811 }
812
813 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000814 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800815 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
816 expectedFlags);
817 }
818
819 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000820 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800821 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
822 expectedFlags);
823 }
824
Svet Ganov5d3bc372020-01-26 23:11:07 -0800825 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000826 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
827 int32_t expectedFlags = 0) {
828 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
829 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -0800830 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
831 }
832
833 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000834 int32_t expectedFlags = 0) {
835 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
836 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -0800837 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
838 }
839
840 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000841 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000842 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
843 expectedFlags);
844 }
845
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500846 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
847 int32_t expectedFlags = 0) {
848 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
849 expectedFlags);
850 }
851
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100852 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
853 ASSERT_NE(mInputReceiver, nullptr)
854 << "Cannot consume events from a window with no receiver";
855 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
856 }
857
chaviwd1c23182019-12-20 18:44:56 -0800858 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
859 int32_t expectedFlags) {
860 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
861 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
862 expectedFlags);
863 }
864
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700865 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700866 if (mInputReceiver == nullptr) {
867 ADD_FAILURE() << "Invalid receive event on window with no receiver";
868 return std::nullopt;
869 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700870 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700871 }
872
873 void finishEvent(uint32_t sequenceNum) {
874 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
875 mInputReceiver->finishEvent(sequenceNum);
876 }
877
chaviwaf87b3e2019-10-01 16:59:28 -0700878 InputEvent* consume() {
879 if (mInputReceiver == nullptr) {
880 return nullptr;
881 }
882 return mInputReceiver->consume();
883 }
884
Arthur Hungb92218b2018-08-14 12:00:21 +0800885 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500886 if (mInputReceiver == nullptr &&
887 mInfo.inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL)) {
888 return; // Can't receive events if the window does not have input channel
889 }
890 ASSERT_NE(nullptr, mInputReceiver)
891 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -0800892 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800893 }
894
chaviwaf87b3e2019-10-01 16:59:28 -0700895 sp<IBinder> getToken() { return mInfo.token; }
896
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100897 const std::string& getName() { return mName; }
898
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000899 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
900 mInfo.ownerPid = ownerPid;
901 mInfo.ownerUid = ownerUid;
902 }
903
chaviwd1c23182019-12-20 18:44:56 -0800904private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100905 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800906 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700907 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800908};
909
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700910std::atomic<int32_t> FakeWindowHandle::sId{1};
911
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800912static InputEventInjectionResult injectKey(
913 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
914 int32_t displayId = ADISPLAY_ID_NONE,
915 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
916 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800917 KeyEvent event;
918 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
919
920 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800921 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700922 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
923 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800924
925 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700926 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
927 injectionTimeout,
928 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
Arthur Hungb92218b2018-08-14 12:00:21 +0800929}
930
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800931static InputEventInjectionResult injectKeyDown(const sp<InputDispatcher>& dispatcher,
932 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700933 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
934}
935
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800936static InputEventInjectionResult injectKeyUp(const sp<InputDispatcher>& dispatcher,
937 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700938 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
939}
940
Garfield Tandf26e862020-07-01 20:18:19 -0700941class PointerBuilder {
942public:
943 PointerBuilder(int32_t id, int32_t toolType) {
944 mProperties.clear();
945 mProperties.id = id;
946 mProperties.toolType = toolType;
947 mCoords.clear();
948 }
949
950 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
951
952 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
953
954 PointerBuilder& axis(int32_t axis, float value) {
955 mCoords.setAxisValue(axis, value);
956 return *this;
957 }
958
959 PointerProperties buildProperties() const { return mProperties; }
960
961 PointerCoords buildCoords() const { return mCoords; }
962
963private:
964 PointerProperties mProperties;
965 PointerCoords mCoords;
966};
967
968class MotionEventBuilder {
969public:
970 MotionEventBuilder(int32_t action, int32_t source) {
971 mAction = action;
972 mSource = source;
973 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
974 }
975
976 MotionEventBuilder& eventTime(nsecs_t eventTime) {
977 mEventTime = eventTime;
978 return *this;
979 }
980
981 MotionEventBuilder& displayId(int32_t displayId) {
982 mDisplayId = displayId;
983 return *this;
984 }
985
986 MotionEventBuilder& actionButton(int32_t actionButton) {
987 mActionButton = actionButton;
988 return *this;
989 }
990
991 MotionEventBuilder& buttonState(int32_t actionButton) {
992 mActionButton = actionButton;
993 return *this;
994 }
995
996 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
997 mRawXCursorPosition = rawXCursorPosition;
998 return *this;
999 }
1000
1001 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1002 mRawYCursorPosition = rawYCursorPosition;
1003 return *this;
1004 }
1005
1006 MotionEventBuilder& pointer(PointerBuilder pointer) {
1007 mPointers.push_back(pointer);
1008 return *this;
1009 }
1010
1011 MotionEvent build() {
1012 std::vector<PointerProperties> pointerProperties;
1013 std::vector<PointerCoords> pointerCoords;
1014 for (const PointerBuilder& pointer : mPointers) {
1015 pointerProperties.push_back(pointer.buildProperties());
1016 pointerCoords.push_back(pointer.buildCoords());
1017 }
1018
1019 // Set mouse cursor position for the most common cases to avoid boilerplate.
1020 if (mSource == AINPUT_SOURCE_MOUSE &&
1021 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1022 mPointers.size() == 1) {
1023 mRawXCursorPosition = pointerCoords[0].getX();
1024 mRawYCursorPosition = pointerCoords[0].getY();
1025 }
1026
1027 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001028 ui::Transform identityTransform;
Garfield Tandf26e862020-07-01 20:18:19 -07001029 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
1030 mAction, mActionButton, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001031 mButtonState, MotionClassification::NONE, identityTransform,
1032 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
1033 mRawYCursorPosition, mEventTime, mEventTime, mPointers.size(),
1034 pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001035
1036 return event;
1037 }
1038
1039private:
1040 int32_t mAction;
1041 int32_t mSource;
1042 nsecs_t mEventTime;
1043 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1044 int32_t mActionButton{0};
1045 int32_t mButtonState{0};
1046 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1047 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1048
1049 std::vector<PointerBuilder> mPointers;
1050};
1051
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001052static InputEventInjectionResult injectMotionEvent(
Garfield Tandf26e862020-07-01 20:18:19 -07001053 const sp<InputDispatcher>& dispatcher, const MotionEvent& event,
1054 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001055 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT) {
Garfield Tandf26e862020-07-01 20:18:19 -07001056 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
1057 injectionTimeout,
1058 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
1059}
1060
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001061static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001062 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
1063 const PointF& position,
1064 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001065 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1066 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001067 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001068 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Garfield Tandf26e862020-07-01 20:18:19 -07001069 MotionEvent event = MotionEventBuilder(action, source)
1070 .displayId(displayId)
1071 .eventTime(eventTime)
1072 .rawXCursorPosition(cursorPosition.x)
1073 .rawYCursorPosition(cursorPosition.y)
1074 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1075 .x(position.x)
1076 .y(position.y))
1077 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001078
1079 // Inject event until dispatch out.
Garfield Tandf26e862020-07-01 20:18:19 -07001080 return injectMotionEvent(dispatcher, event);
Arthur Hungb92218b2018-08-14 12:00:21 +08001081}
1082
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001083static InputEventInjectionResult injectMotionDown(const sp<InputDispatcher>& dispatcher,
1084 int32_t source, int32_t displayId,
1085 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001086 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001087}
1088
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001089static InputEventInjectionResult injectMotionUp(const sp<InputDispatcher>& dispatcher,
1090 int32_t source, int32_t displayId,
1091 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001092 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001093}
1094
Jackal Guof9696682018-10-05 12:23:23 +08001095static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1096 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1097 // Define a valid key event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001098 NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
1099 POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A,
1100 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001101
1102 return args;
1103}
1104
chaviwd1c23182019-12-20 18:44:56 -08001105static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1106 const std::vector<PointF>& points) {
1107 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001108 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1109 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1110 }
1111
chaviwd1c23182019-12-20 18:44:56 -08001112 PointerProperties pointerProperties[pointerCount];
1113 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001114
chaviwd1c23182019-12-20 18:44:56 -08001115 for (size_t i = 0; i < pointerCount; i++) {
1116 pointerProperties[i].clear();
1117 pointerProperties[i].id = i;
1118 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001119
chaviwd1c23182019-12-20 18:44:56 -08001120 pointerCoords[i].clear();
1121 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1122 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1123 }
Jackal Guof9696682018-10-05 12:23:23 +08001124
1125 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1126 // Define a valid motion event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001127 NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001128 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1129 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001130 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1131 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001132 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1133 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001134
1135 return args;
1136}
1137
chaviwd1c23182019-12-20 18:44:56 -08001138static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1139 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1140}
1141
Arthur Hungb92218b2018-08-14 12:00:21 +08001142TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001143 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001144 sp<FakeWindowHandle> window =
1145 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001146
Arthur Hung72d8dc32020-03-28 00:48:39 +00001147 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001148 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1149 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1150 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001151
1152 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001153 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001154}
1155
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001156/**
1157 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1158 * To ensure that window receives only events that were directly inside of it, add
1159 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1160 * when finding touched windows.
1161 * This test serves as a sanity check for the next test, where setInputWindows is
1162 * called twice.
1163 */
1164TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001165 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001166 sp<FakeWindowHandle> window =
1167 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1168 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001169 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001170
1171 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001172 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001173 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1174 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001175 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001176
1177 // Window should receive motion event.
1178 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1179}
1180
1181/**
1182 * Calling setInputWindows twice, with the same info, should not cause any issues.
1183 * To ensure that window receives only events that were directly inside of it, add
1184 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1185 * when finding touched windows.
1186 */
1187TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001188 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001189 sp<FakeWindowHandle> window =
1190 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1191 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001192 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001193
1194 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1195 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001196 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001197 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1198 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001199 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001200
1201 // Window should receive motion event.
1202 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1203}
1204
Arthur Hungb92218b2018-08-14 12:00:21 +08001205// The foreground window should receive the first touch down event.
1206TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001207 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001208 sp<FakeWindowHandle> windowTop =
1209 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1210 sp<FakeWindowHandle> windowSecond =
1211 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001212
Arthur Hung72d8dc32020-03-28 00:48:39 +00001213 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001214 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1215 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1216 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001217
1218 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001219 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001220 windowSecond->assertNoEvents();
1221}
1222
Garfield Tandf26e862020-07-01 20:18:19 -07001223TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001224 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001225 sp<FakeWindowHandle> windowLeft =
1226 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1227 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001228 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001229 sp<FakeWindowHandle> windowRight =
1230 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1231 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001232 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001233
1234 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1235
1236 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
1237
1238 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001239 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001240 injectMotionEvent(mDispatcher,
1241 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1242 AINPUT_SOURCE_MOUSE)
1243 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1244 .x(900)
1245 .y(400))
1246 .build()));
1247 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1248 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1249 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1250 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1251
1252 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001254 injectMotionEvent(mDispatcher,
1255 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1256 AINPUT_SOURCE_MOUSE)
1257 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1258 .x(300)
1259 .y(400))
1260 .build()));
1261 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1262 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1263 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1264 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1265 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1266 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1267
1268 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001270 injectMotionEvent(mDispatcher,
1271 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1272 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1273 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1274 .x(300)
1275 .y(400))
1276 .build()));
1277 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1278
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001279 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001280 injectMotionEvent(mDispatcher,
1281 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1282 AINPUT_SOURCE_MOUSE)
1283 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1284 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1285 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1286 .x(300)
1287 .y(400))
1288 .build()));
1289 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1290 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1291
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001293 injectMotionEvent(mDispatcher,
1294 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1295 AINPUT_SOURCE_MOUSE)
1296 .buttonState(0)
1297 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1298 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1299 .x(300)
1300 .y(400))
1301 .build()));
1302 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1303 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1304
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001306 injectMotionEvent(mDispatcher,
1307 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1308 .buttonState(0)
1309 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1310 .x(300)
1311 .y(400))
1312 .build()));
1313 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1314
1315 // Move mouse cursor back to right window
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_HOVER_MOVE,
1319 AINPUT_SOURCE_MOUSE)
1320 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1321 .x(900)
1322 .y(400))
1323 .build()));
1324 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1325 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1326 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1327 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1328 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1329 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1330}
1331
1332// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
1333// directly in this test.
1334TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001335 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001336 sp<FakeWindowHandle> window =
1337 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1338 window->setFrame(Rect(0, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001339 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001340
1341 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1342
1343 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1344
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001346 injectMotionEvent(mDispatcher,
1347 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
1348 AINPUT_SOURCE_MOUSE)
1349 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1350 .x(300)
1351 .y(400))
1352 .build()));
1353 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1354 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1355
1356 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001357 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001358 injectMotionEvent(mDispatcher,
1359 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1360 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1361 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1362 .x(300)
1363 .y(400))
1364 .build()));
1365 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1366
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001367 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001368 injectMotionEvent(mDispatcher,
1369 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1370 AINPUT_SOURCE_MOUSE)
1371 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1372 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1373 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1374 .x(300)
1375 .y(400))
1376 .build()));
1377 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1378 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1379
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001380 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001381 injectMotionEvent(mDispatcher,
1382 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1383 AINPUT_SOURCE_MOUSE)
1384 .buttonState(0)
1385 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1386 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1387 .x(300)
1388 .y(400))
1389 .build()));
1390 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1391 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1392
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001393 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001394 injectMotionEvent(mDispatcher,
1395 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1396 .buttonState(0)
1397 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1398 .x(300)
1399 .y(400))
1400 .build()));
1401 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1402
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001403 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001404 injectMotionEvent(mDispatcher,
1405 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
1406 AINPUT_SOURCE_MOUSE)
1407 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1408 .x(300)
1409 .y(400))
1410 .build()));
1411 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1412 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1413}
1414
Garfield Tan00f511d2019-06-12 16:55:40 -07001415TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07001416 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07001417
1418 sp<FakeWindowHandle> windowLeft =
1419 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1420 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001421 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001422 sp<FakeWindowHandle> windowRight =
1423 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1424 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001425 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001426
1427 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1428
Arthur Hung72d8dc32020-03-28 00:48:39 +00001429 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001430
1431 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1432 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07001434 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001435 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001436 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001437 windowRight->assertNoEvents();
1438}
1439
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001440TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001441 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001442 sp<FakeWindowHandle> window =
1443 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07001444 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001445
Arthur Hung72d8dc32020-03-28 00:48:39 +00001446 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001447 setFocusedWindow(window);
1448
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001449 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001450
1451 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1452 mDispatcher->notifyKey(&keyArgs);
1453
1454 // Window should receive key down event.
1455 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1456
1457 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1458 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001459 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001460 mDispatcher->notifyDeviceReset(&args);
1461 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1462 AKEY_EVENT_FLAG_CANCELED);
1463}
1464
1465TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001466 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001467 sp<FakeWindowHandle> window =
1468 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1469
Arthur Hung72d8dc32020-03-28 00:48:39 +00001470 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001471
1472 NotifyMotionArgs motionArgs =
1473 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1474 ADISPLAY_ID_DEFAULT);
1475 mDispatcher->notifyMotion(&motionArgs);
1476
1477 // Window should receive motion down event.
1478 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1479
1480 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1481 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001482 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001483 mDispatcher->notifyDeviceReset(&args);
1484 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1485 0 /*expectedFlags*/);
1486}
1487
Svet Ganov5d3bc372020-01-26 23:11:07 -08001488TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07001489 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001490
1491 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001492 sp<FakeWindowHandle> firstWindow =
1493 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1494 sp<FakeWindowHandle> secondWindow =
1495 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001496
1497 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001498 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001499
1500 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001501 NotifyMotionArgs downMotionArgs =
1502 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1503 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001504 mDispatcher->notifyMotion(&downMotionArgs);
1505 // Only the first window should get the down event
1506 firstWindow->consumeMotionDown();
1507 secondWindow->assertNoEvents();
1508
1509 // Transfer touch focus to the second window
1510 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1511 // The first window gets cancel and the second gets down
1512 firstWindow->consumeMotionCancel();
1513 secondWindow->consumeMotionDown();
1514
1515 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001516 NotifyMotionArgs upMotionArgs =
1517 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1518 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001519 mDispatcher->notifyMotion(&upMotionArgs);
1520 // The first window gets no events and the second gets up
1521 firstWindow->assertNoEvents();
1522 secondWindow->consumeMotionUp();
1523}
1524
1525TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001526 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001527
1528 PointF touchPoint = {10, 10};
1529
1530 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001531 sp<FakeWindowHandle> firstWindow =
1532 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1533 sp<FakeWindowHandle> secondWindow =
1534 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001535
1536 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001537 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001538
1539 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001540 NotifyMotionArgs downMotionArgs =
1541 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1542 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001543 mDispatcher->notifyMotion(&downMotionArgs);
1544 // Only the first window should get the down event
1545 firstWindow->consumeMotionDown();
1546 secondWindow->assertNoEvents();
1547
1548 // Send pointer down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001549 NotifyMotionArgs pointerDownMotionArgs =
1550 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
1551 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1552 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1553 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001554 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1555 // Only the first window should get the pointer down event
1556 firstWindow->consumeMotionPointerDown(1);
1557 secondWindow->assertNoEvents();
1558
1559 // Transfer touch focus to the second window
1560 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1561 // The first window gets cancel and the second gets down and pointer down
1562 firstWindow->consumeMotionCancel();
1563 secondWindow->consumeMotionDown();
1564 secondWindow->consumeMotionPointerDown(1);
1565
1566 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001567 NotifyMotionArgs pointerUpMotionArgs =
1568 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
1569 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1570 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1571 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001572 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1573 // The first window gets nothing and the second gets pointer up
1574 firstWindow->assertNoEvents();
1575 secondWindow->consumeMotionPointerUp(1);
1576
1577 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001578 NotifyMotionArgs upMotionArgs =
1579 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1580 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001581 mDispatcher->notifyMotion(&upMotionArgs);
1582 // The first window gets nothing and the second gets up
1583 firstWindow->assertNoEvents();
1584 secondWindow->consumeMotionUp();
1585}
1586
1587TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001588 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001589
1590 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001591 sp<FakeWindowHandle> firstWindow =
1592 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001593 firstWindow->setFrame(Rect(0, 0, 600, 400));
Michael Wright44753b12020-07-08 13:48:11 +01001594 firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1595 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001596
1597 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001598 sp<FakeWindowHandle> secondWindow =
1599 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001600 secondWindow->setFrame(Rect(0, 400, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001601 secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1602 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001603
1604 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001605 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001606
1607 PointF pointInFirst = {300, 200};
1608 PointF pointInSecond = {300, 600};
1609
1610 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001611 NotifyMotionArgs firstDownMotionArgs =
1612 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1613 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001614 mDispatcher->notifyMotion(&firstDownMotionArgs);
1615 // Only the first window should get the down event
1616 firstWindow->consumeMotionDown();
1617 secondWindow->assertNoEvents();
1618
1619 // Send down to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001620 NotifyMotionArgs secondDownMotionArgs =
1621 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
1622 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1623 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1624 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001625 mDispatcher->notifyMotion(&secondDownMotionArgs);
1626 // The first window gets a move and the second a down
1627 firstWindow->consumeMotionMove();
1628 secondWindow->consumeMotionDown();
1629
1630 // Transfer touch focus to the second window
1631 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1632 // The first window gets cancel and the new gets pointer down (it already saw down)
1633 firstWindow->consumeMotionCancel();
1634 secondWindow->consumeMotionPointerDown(1);
1635
1636 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001637 NotifyMotionArgs pointerUpMotionArgs =
1638 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
1639 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1640 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1641 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001642 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1643 // The first window gets nothing and the second gets pointer up
1644 firstWindow->assertNoEvents();
1645 secondWindow->consumeMotionPointerUp(1);
1646
1647 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001648 NotifyMotionArgs upMotionArgs =
1649 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1650 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001651 mDispatcher->notifyMotion(&upMotionArgs);
1652 // The first window gets nothing and the second gets up
1653 firstWindow->assertNoEvents();
1654 secondWindow->consumeMotionUp();
1655}
1656
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001657TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001658 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001659 sp<FakeWindowHandle> window =
1660 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1661
Vishnu Nair47074b82020-08-14 11:54:47 -07001662 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001663 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001664 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001665
1666 window->consumeFocusEvent(true);
1667
1668 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1669 mDispatcher->notifyKey(&keyArgs);
1670
1671 // Window should receive key down event.
1672 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1673}
1674
1675TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001676 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001677 sp<FakeWindowHandle> window =
1678 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1679
Arthur Hung72d8dc32020-03-28 00:48:39 +00001680 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001681
1682 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1683 mDispatcher->notifyKey(&keyArgs);
1684 mDispatcher->waitForIdle();
1685
1686 window->assertNoEvents();
1687}
1688
1689// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1690TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07001691 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001692 sp<FakeWindowHandle> window =
1693 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1694
Arthur Hung72d8dc32020-03-28 00:48:39 +00001695 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001696
1697 // Send key
1698 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1699 mDispatcher->notifyKey(&keyArgs);
1700 // Send motion
1701 NotifyMotionArgs motionArgs =
1702 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1703 ADISPLAY_ID_DEFAULT);
1704 mDispatcher->notifyMotion(&motionArgs);
1705
1706 // Window should receive only the motion event
1707 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1708 window->assertNoEvents(); // Key event or focus event will not be received
1709}
1710
chaviwd1c23182019-12-20 18:44:56 -08001711class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001712public:
1713 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001714 int32_t displayId, bool isGestureMonitor = false) {
Garfield Tan15601662020-09-22 15:32:38 -07001715 base::Result<std::unique_ptr<InputChannel>> channel =
1716 dispatcher->createInputMonitor(displayId, isGestureMonitor, name);
1717 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00001718 }
1719
chaviwd1c23182019-12-20 18:44:56 -08001720 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1721
1722 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1723 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1724 expectedDisplayId, expectedFlags);
1725 }
1726
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001727 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
1728
1729 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1730
chaviwd1c23182019-12-20 18:44:56 -08001731 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1732 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1733 expectedDisplayId, expectedFlags);
1734 }
1735
1736 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1737 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1738 expectedDisplayId, expectedFlags);
1739 }
1740
1741 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1742
1743private:
1744 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001745};
1746
1747// Tests for gesture monitors
1748TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07001749 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001750 sp<FakeWindowHandle> window =
1751 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001752 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001753
chaviwd1c23182019-12-20 18:44:56 -08001754 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1755 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001756
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00001758 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001759 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00001760 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001761 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001762}
1763
1764TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07001765 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001766 sp<FakeWindowHandle> window =
1767 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1768
1769 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07001770 window->setFocusable(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001771
Arthur Hung72d8dc32020-03-28 00:48:39 +00001772 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001773 setFocusedWindow(window);
1774
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001775 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001776
chaviwd1c23182019-12-20 18:44:56 -08001777 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1778 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001779
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1781 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00001782 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001783 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001784}
1785
1786TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001787 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001788 sp<FakeWindowHandle> window =
1789 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001790 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001791
chaviwd1c23182019-12-20 18:44:56 -08001792 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1793 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001794
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00001796 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001797 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00001798 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001799 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001800
1801 window->releaseChannel();
1802
chaviwd1c23182019-12-20 18:44:56 -08001803 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001804
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001805 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00001806 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001807 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001808 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001809}
1810
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001811TEST_F(InputDispatcherTest, UnresponsiveGestureMonitor_GetsAnr) {
1812 FakeMonitorReceiver monitor =
1813 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
1814 true /*isGestureMonitor*/);
1815
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001817 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
1818 std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
1819 ASSERT_TRUE(consumeSeq);
1820
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001821 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(DISPATCHING_TIMEOUT,
1822 monitor.getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001823 monitor.finishEvent(*consumeSeq);
1824 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001825 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(monitor.getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001826}
1827
chaviw81e2bb92019-12-18 15:03:51 -08001828TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001829 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
chaviw81e2bb92019-12-18 15:03:51 -08001830 sp<FakeWindowHandle> window =
1831 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1832
Arthur Hung72d8dc32020-03-28 00:48:39 +00001833 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08001834
1835 NotifyMotionArgs motionArgs =
1836 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1837 ADISPLAY_ID_DEFAULT);
1838
1839 mDispatcher->notifyMotion(&motionArgs);
1840 // Window should receive motion down event.
1841 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1842
1843 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001844 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08001845 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1846 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1847 motionArgs.pointerCoords[0].getX() - 10);
1848
1849 mDispatcher->notifyMotion(&motionArgs);
1850 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1851 0 /*expectedFlags*/);
1852}
1853
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001854/**
1855 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1856 * the device default right away. In the test scenario, we check both the default value,
1857 * and the action of enabling / disabling.
1858 */
1859TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07001860 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001861 sp<FakeWindowHandle> window =
1862 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1863
1864 // Set focused application.
1865 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07001866 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001867
1868 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00001869 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001870 setFocusedWindow(window);
1871
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001872 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1873
1874 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07001875 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001876 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001877 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1878
1879 SCOPED_TRACE("Disable touch mode");
1880 mDispatcher->setInTouchMode(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07001881 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001882 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001883 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001884 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1885
1886 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07001887 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001888 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001889 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1890
1891 SCOPED_TRACE("Enable touch mode again");
1892 mDispatcher->setInTouchMode(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07001893 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001894 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001895 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001896 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1897
1898 window->assertNoEvents();
1899}
1900
Gang Wange9087892020-01-07 12:17:14 -05001901TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001902 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Gang Wange9087892020-01-07 12:17:14 -05001903 sp<FakeWindowHandle> window =
1904 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1905
1906 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07001907 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05001908
Arthur Hung72d8dc32020-03-28 00:48:39 +00001909 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001910 setFocusedWindow(window);
1911
Gang Wange9087892020-01-07 12:17:14 -05001912 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1913
1914 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1915 mDispatcher->notifyKey(&keyArgs);
1916
1917 InputEvent* event = window->consume();
1918 ASSERT_NE(event, nullptr);
1919
1920 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1921 ASSERT_NE(verified, nullptr);
1922 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
1923
1924 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
1925 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
1926 ASSERT_EQ(keyArgs.source, verified->source);
1927 ASSERT_EQ(keyArgs.displayId, verified->displayId);
1928
1929 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
1930
1931 ASSERT_EQ(keyArgs.action, verifiedKey.action);
1932 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05001933 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
1934 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
1935 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
1936 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
1937 ASSERT_EQ(0, verifiedKey.repeatCount);
1938}
1939
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001940TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001941 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001942 sp<FakeWindowHandle> window =
1943 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1944
1945 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1946
Arthur Hung72d8dc32020-03-28 00:48:39 +00001947 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001948
1949 NotifyMotionArgs motionArgs =
1950 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1951 ADISPLAY_ID_DEFAULT);
1952 mDispatcher->notifyMotion(&motionArgs);
1953
1954 InputEvent* event = window->consume();
1955 ASSERT_NE(event, nullptr);
1956
1957 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1958 ASSERT_NE(verified, nullptr);
1959 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
1960
1961 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
1962 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
1963 EXPECT_EQ(motionArgs.source, verified->source);
1964 EXPECT_EQ(motionArgs.displayId, verified->displayId);
1965
1966 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
1967
1968 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
1969 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
1970 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
1971 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
1972 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
1973 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
1974 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
1975}
1976
chaviw09c8d2d2020-08-24 15:48:26 -07001977/**
1978 * Ensure that separate calls to sign the same data are generating the same key.
1979 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
1980 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
1981 * tests.
1982 */
1983TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
1984 KeyEvent event = getTestKeyEvent();
1985 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
1986
1987 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
1988 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
1989 ASSERT_EQ(hmac1, hmac2);
1990}
1991
1992/**
1993 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
1994 */
1995TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
1996 KeyEvent event = getTestKeyEvent();
1997 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
1998 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
1999
2000 verifiedEvent.deviceId += 1;
2001 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2002
2003 verifiedEvent.source += 1;
2004 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2005
2006 verifiedEvent.eventTimeNanos += 1;
2007 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2008
2009 verifiedEvent.displayId += 1;
2010 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2011
2012 verifiedEvent.action += 1;
2013 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2014
2015 verifiedEvent.downTimeNanos += 1;
2016 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2017
2018 verifiedEvent.flags += 1;
2019 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2020
2021 verifiedEvent.keyCode += 1;
2022 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2023
2024 verifiedEvent.scanCode += 1;
2025 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2026
2027 verifiedEvent.metaState += 1;
2028 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2029
2030 verifiedEvent.repeatCount += 1;
2031 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2032}
2033
Vishnu Nair958da932020-08-21 17:12:37 -07002034TEST_F(InputDispatcherTest, SetFocusedWindow) {
2035 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2036 sp<FakeWindowHandle> windowTop =
2037 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2038 sp<FakeWindowHandle> windowSecond =
2039 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2040 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2041
2042 // Top window is also focusable but is not granted focus.
2043 windowTop->setFocusable(true);
2044 windowSecond->setFocusable(true);
2045 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2046 setFocusedWindow(windowSecond);
2047
2048 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2050 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002051
2052 // Focused window should receive event.
2053 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2054 windowTop->assertNoEvents();
2055}
2056
2057TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
2058 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2059 sp<FakeWindowHandle> window =
2060 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2061 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2062
2063 window->setFocusable(true);
2064 // Release channel for window is no longer valid.
2065 window->releaseChannel();
2066 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2067 setFocusedWindow(window);
2068
2069 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002070 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2071 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002072
2073 // window channel is invalid, so it should not receive any input event.
2074 window->assertNoEvents();
2075}
2076
2077TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
2078 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2079 sp<FakeWindowHandle> window =
2080 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2081 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2082
2083 // Window is not focusable.
2084 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2085 setFocusedWindow(window);
2086
2087 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002088 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2089 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002090
2091 // window is invalid, so it should not receive any input event.
2092 window->assertNoEvents();
2093}
2094
2095TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
2096 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2097 sp<FakeWindowHandle> windowTop =
2098 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2099 sp<FakeWindowHandle> windowSecond =
2100 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2101 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2102
2103 windowTop->setFocusable(true);
2104 windowSecond->setFocusable(true);
2105 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2106 setFocusedWindow(windowTop);
2107 windowTop->consumeFocusEvent(true);
2108
2109 setFocusedWindow(windowSecond, windowTop);
2110 windowSecond->consumeFocusEvent(true);
2111 windowTop->consumeFocusEvent(false);
2112
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002113 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2114 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002115
2116 // Focused window should receive event.
2117 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2118}
2119
2120TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
2121 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2122 sp<FakeWindowHandle> windowTop =
2123 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2124 sp<FakeWindowHandle> windowSecond =
2125 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2126 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2127
2128 windowTop->setFocusable(true);
2129 windowSecond->setFocusable(true);
2130 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2131 setFocusedWindow(windowSecond, windowTop);
2132
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002133 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2134 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002135
2136 // Event should be dropped.
2137 windowTop->assertNoEvents();
2138 windowSecond->assertNoEvents();
2139}
2140
2141TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
2142 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2143 sp<FakeWindowHandle> window =
2144 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2145 sp<FakeWindowHandle> previousFocusedWindow =
2146 new FakeWindowHandle(application, mDispatcher, "previousFocusedWindow",
2147 ADISPLAY_ID_DEFAULT);
2148 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2149
2150 window->setFocusable(true);
2151 previousFocusedWindow->setFocusable(true);
2152 window->setVisible(false);
2153 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
2154 setFocusedWindow(previousFocusedWindow);
2155 previousFocusedWindow->consumeFocusEvent(true);
2156
2157 // Requesting focus on invisible window takes focus from currently focused window.
2158 setFocusedWindow(window);
2159 previousFocusedWindow->consumeFocusEvent(false);
2160
2161 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002162 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07002163 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002164 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07002165
2166 // Window does not get focus event or key down.
2167 window->assertNoEvents();
2168
2169 // Window becomes visible.
2170 window->setVisible(true);
2171 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2172
2173 // Window receives focus event.
2174 window->consumeFocusEvent(true);
2175 // Focused window receives key down.
2176 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2177}
2178
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002179/**
2180 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
2181 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
2182 * of the 'slipperyEnterWindow'.
2183 *
2184 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
2185 * a way so that the touched location is no longer covered by the top window.
2186 *
2187 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
2188 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
2189 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
2190 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
2191 * with ACTION_DOWN).
2192 * Thus, the touch has been transferred from the top window into the bottom window, because the top
2193 * window moved itself away from the touched location and had Flag::SLIPPERY.
2194 *
2195 * Even though the top window moved away from the touched location, it is still obscuring the bottom
2196 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
2197 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
2198 *
2199 * In this test, we ensure that the event received by the bottom window has
2200 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
2201 */
2202TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
2203 constexpr int32_t SLIPPERY_PID = INJECTOR_PID + 1;
2204 constexpr int32_t SLIPPERY_UID = INJECTOR_UID + 1;
2205
2206 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2207 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2208
2209 sp<FakeWindowHandle> slipperyExitWindow =
2210 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2211 slipperyExitWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2212 InputWindowInfo::Flag::SLIPPERY);
2213 // Make sure this one overlaps the bottom window
2214 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
2215 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
2216 // one. Windows with the same owner are not considered to be occluding each other.
2217 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
2218
2219 sp<FakeWindowHandle> slipperyEnterWindow =
2220 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2221 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
2222
2223 mDispatcher->setInputWindows(
2224 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
2225
2226 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
2227 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2228 ADISPLAY_ID_DEFAULT, {{50, 50}});
2229 mDispatcher->notifyMotion(&args);
2230 slipperyExitWindow->consumeMotionDown();
2231 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
2232 mDispatcher->setInputWindows(
2233 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
2234
2235 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2236 ADISPLAY_ID_DEFAULT, {{51, 51}});
2237 mDispatcher->notifyMotion(&args);
2238
2239 slipperyExitWindow->consumeMotionCancel();
2240
2241 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
2242 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
2243}
2244
Garfield Tan1c7bc862020-01-28 13:24:04 -08002245class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
2246protected:
2247 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
2248 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
2249
Chris Yea209fde2020-07-22 13:54:51 -07002250 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002251 sp<FakeWindowHandle> mWindow;
2252
2253 virtual void SetUp() override {
2254 mFakePolicy = new FakeInputDispatcherPolicy();
2255 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
2256 mDispatcher = new InputDispatcher(mFakePolicy);
2257 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
2258 ASSERT_EQ(OK, mDispatcher->start());
2259
2260 setUpWindow();
2261 }
2262
2263 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07002264 mApp = std::make_shared<FakeApplicationHandle>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08002265 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2266
Vishnu Nair47074b82020-08-14 11:54:47 -07002267 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002268 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002269 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002270 mWindow->consumeFocusEvent(true);
2271 }
2272
Chris Ye2ad95392020-09-01 13:44:44 -07002273 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08002274 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07002275 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002276 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
2277 mDispatcher->notifyKey(&keyArgs);
2278
2279 // Window should receive key down event.
2280 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2281 }
2282
2283 void expectKeyRepeatOnce(int32_t repeatCount) {
2284 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
2285 InputEvent* repeatEvent = mWindow->consume();
2286 ASSERT_NE(nullptr, repeatEvent);
2287
2288 uint32_t eventType = repeatEvent->getType();
2289 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
2290
2291 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
2292 uint32_t eventAction = repeatKeyEvent->getAction();
2293 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
2294 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
2295 }
2296
Chris Ye2ad95392020-09-01 13:44:44 -07002297 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08002298 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07002299 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002300 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
2301 mDispatcher->notifyKey(&keyArgs);
2302
2303 // Window should receive key down event.
2304 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
2305 0 /*expectedFlags*/);
2306 }
2307};
2308
2309TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Chris Ye2ad95392020-09-01 13:44:44 -07002310 sendAndConsumeKeyDown(1 /* deviceId */);
2311 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2312 expectKeyRepeatOnce(repeatCount);
2313 }
2314}
2315
2316TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
2317 sendAndConsumeKeyDown(1 /* deviceId */);
2318 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2319 expectKeyRepeatOnce(repeatCount);
2320 }
2321 sendAndConsumeKeyDown(2 /* deviceId */);
2322 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08002323 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2324 expectKeyRepeatOnce(repeatCount);
2325 }
2326}
2327
2328TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Chris Ye2ad95392020-09-01 13:44:44 -07002329 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002330 expectKeyRepeatOnce(1 /*repeatCount*/);
Chris Ye2ad95392020-09-01 13:44:44 -07002331 sendAndConsumeKeyUp(1 /* deviceId */);
2332 mWindow->assertNoEvents();
2333}
2334
2335TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
2336 sendAndConsumeKeyDown(1 /* deviceId */);
2337 expectKeyRepeatOnce(1 /*repeatCount*/);
2338 sendAndConsumeKeyDown(2 /* deviceId */);
2339 expectKeyRepeatOnce(1 /*repeatCount*/);
2340 // Stale key up from device 1.
2341 sendAndConsumeKeyUp(1 /* deviceId */);
2342 // Device 2 is still down, keep repeating
2343 expectKeyRepeatOnce(2 /*repeatCount*/);
2344 expectKeyRepeatOnce(3 /*repeatCount*/);
2345 // Device 2 key up
2346 sendAndConsumeKeyUp(2 /* deviceId */);
2347 mWindow->assertNoEvents();
2348}
2349
2350TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
2351 sendAndConsumeKeyDown(1 /* deviceId */);
2352 expectKeyRepeatOnce(1 /*repeatCount*/);
2353 sendAndConsumeKeyDown(2 /* deviceId */);
2354 expectKeyRepeatOnce(1 /*repeatCount*/);
2355 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
2356 sendAndConsumeKeyUp(2 /* deviceId */);
2357 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08002358 mWindow->assertNoEvents();
2359}
2360
2361TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Chris Ye2ad95392020-09-01 13:44:44 -07002362 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002363 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2364 InputEvent* repeatEvent = mWindow->consume();
2365 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2366 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
2367 IdGenerator::getSource(repeatEvent->getId()));
2368 }
2369}
2370
2371TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Chris Ye2ad95392020-09-01 13:44:44 -07002372 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002373
2374 std::unordered_set<int32_t> idSet;
2375 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2376 InputEvent* repeatEvent = mWindow->consume();
2377 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2378 int32_t id = repeatEvent->getId();
2379 EXPECT_EQ(idSet.end(), idSet.find(id));
2380 idSet.insert(id);
2381 }
2382}
2383
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002384/* Test InputDispatcher for MultiDisplay */
2385class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
2386public:
2387 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002388 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002389 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08002390
Chris Yea209fde2020-07-22 13:54:51 -07002391 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002392 windowInPrimary =
2393 new FakeWindowHandle(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002394
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002395 // Set focus window for primary display, but focused display would be second one.
2396 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07002397 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002398 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002399 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002400 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08002401
Chris Yea209fde2020-07-22 13:54:51 -07002402 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002403 windowInSecondary =
2404 new FakeWindowHandle(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002405 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002406 // Set focus display to second one.
2407 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
2408 // Set focus window for second display.
2409 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07002410 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002411 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002412 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002413 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002414 }
2415
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002416 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002417 InputDispatcherTest::TearDown();
2418
Chris Yea209fde2020-07-22 13:54:51 -07002419 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002420 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07002421 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002422 windowInSecondary.clear();
2423 }
2424
2425protected:
Chris Yea209fde2020-07-22 13:54:51 -07002426 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002427 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07002428 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002429 sp<FakeWindowHandle> windowInSecondary;
2430};
2431
2432TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
2433 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002434 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2435 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2436 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002437 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08002438 windowInSecondary->assertNoEvents();
2439
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002440 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2442 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
2443 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08002444 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002445 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08002446}
2447
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002448TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08002449 // Test inject a key down with display id specified.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2451 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002452 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08002453 windowInSecondary->assertNoEvents();
2454
2455 // Test inject a key down without display id specified.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002456 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2457 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08002458 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002459 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08002460
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002461 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002462 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08002463
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002464 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002465 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
2466 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08002467
2468 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002469 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2470 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08002471 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002472 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08002473 windowInSecondary->assertNoEvents();
2474}
2475
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002476// Test per-display input monitors for motion event.
2477TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08002478 FakeMonitorReceiver monitorInPrimary =
2479 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2480 FakeMonitorReceiver monitorInSecondary =
2481 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002482
2483 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002484 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2485 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2486 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002487 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002488 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002489 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002490 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002491
2492 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002493 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2494 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
2495 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002496 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002497 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002498 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08002499 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002500
2501 // Test inject a non-pointer motion event.
2502 // If specific a display, it will dispatch to the focused window of particular display,
2503 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002504 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2505 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
2506 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002507 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002508 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002509 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002510 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002511}
2512
2513// Test per-display input monitors for key event.
2514TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002515 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08002516 FakeMonitorReceiver monitorInPrimary =
2517 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2518 FakeMonitorReceiver monitorInSecondary =
2519 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002520
2521 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2523 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002524 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002525 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002526 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002527 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002528}
2529
Vishnu Nair958da932020-08-21 17:12:37 -07002530TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
2531 sp<FakeWindowHandle> secondWindowInPrimary =
2532 new FakeWindowHandle(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2533 secondWindowInPrimary->setFocusable(true);
2534 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
2535 setFocusedWindow(secondWindowInPrimary);
2536 windowInPrimary->consumeFocusEvent(false);
2537 secondWindowInPrimary->consumeFocusEvent(true);
2538
2539 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002540 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2541 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002542 windowInPrimary->assertNoEvents();
2543 windowInSecondary->assertNoEvents();
2544 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2545}
2546
Jackal Guof9696682018-10-05 12:23:23 +08002547class InputFilterTest : public InputDispatcherTest {
2548protected:
2549 static constexpr int32_t SECOND_DISPLAY_ID = 1;
2550
2551 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
2552 NotifyMotionArgs motionArgs;
2553
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002554 motionArgs =
2555 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08002556 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002557 motionArgs =
2558 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08002559 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002560 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002561 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002562 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002563 } else {
2564 mFakePolicy->assertFilterInputEventWasNotCalled();
2565 }
2566 }
2567
2568 void testNotifyKey(bool expectToBeFiltered) {
2569 NotifyKeyArgs keyArgs;
2570
2571 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2572 mDispatcher->notifyKey(&keyArgs);
2573 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
2574 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002575 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002576
2577 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002578 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002579 } else {
2580 mFakePolicy->assertFilterInputEventWasNotCalled();
2581 }
2582 }
2583};
2584
2585// Test InputFilter for MotionEvent
2586TEST_F(InputFilterTest, MotionEvent_InputFilter) {
2587 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
2588 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2589 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2590
2591 // Enable InputFilter
2592 mDispatcher->setInputFilterEnabled(true);
2593 // Test touch on both primary and second display, and check if both events are filtered.
2594 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
2595 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
2596
2597 // Disable InputFilter
2598 mDispatcher->setInputFilterEnabled(false);
2599 // Test touch on both primary and second display, and check if both events aren't filtered.
2600 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2601 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2602}
2603
2604// Test InputFilter for KeyEvent
2605TEST_F(InputFilterTest, KeyEvent_InputFilter) {
2606 // Since the InputFilter is disabled by default, check if key event aren't filtered.
2607 testNotifyKey(/*expectToBeFiltered*/ false);
2608
2609 // Enable InputFilter
2610 mDispatcher->setInputFilterEnabled(true);
2611 // Send a key event, and check if it is filtered.
2612 testNotifyKey(/*expectToBeFiltered*/ true);
2613
2614 // Disable InputFilter
2615 mDispatcher->setInputFilterEnabled(false);
2616 // Send a key event, and check if it isn't filtered.
2617 testNotifyKey(/*expectToBeFiltered*/ false);
2618}
2619
chaviwfd6d3512019-03-25 13:23:49 -07002620class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002621 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07002622 InputDispatcherTest::SetUp();
2623
Chris Yea209fde2020-07-22 13:54:51 -07002624 std::shared_ptr<FakeApplicationHandle> application =
2625 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002626 mUnfocusedWindow =
2627 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002628 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
2629 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2630 // window.
Michael Wright44753b12020-07-08 13:48:11 +01002631 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002632
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002633 mFocusedWindow =
2634 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2635 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01002636 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002637
2638 // Set focused application.
2639 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002640 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07002641
2642 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002643 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002644 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002645 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07002646 }
2647
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002648 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07002649 InputDispatcherTest::TearDown();
2650
2651 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002652 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07002653 }
2654
2655protected:
2656 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002657 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002658 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07002659};
2660
2661// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2662// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
2663// the onPointerDownOutsideFocus callback.
2664TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002666 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2667 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002668 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002669 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002670
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002671 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07002672 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
2673}
2674
2675// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
2676// DOWN on the window that doesn't have focus. Ensure no window received the
2677// onPointerDownOutsideFocus callback.
2678TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002680 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002681 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002682 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002683
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002684 ASSERT_TRUE(mDispatcher->waitForIdle());
2685 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002686}
2687
2688// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
2689// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
2690TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2692 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002693 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002694
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002695 ASSERT_TRUE(mDispatcher->waitForIdle());
2696 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002697}
2698
2699// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2700// DOWN on the window that already has focus. Ensure no window received the
2701// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002702TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002703 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002704 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002705 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002706 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002707 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002708
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002709 ASSERT_TRUE(mDispatcher->waitForIdle());
2710 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002711}
2712
chaviwaf87b3e2019-10-01 16:59:28 -07002713// These tests ensures we can send touch events to a single client when there are multiple input
2714// windows that point to the same client token.
2715class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
2716 virtual void SetUp() override {
2717 InputDispatcherTest::SetUp();
2718
Chris Yea209fde2020-07-22 13:54:51 -07002719 std::shared_ptr<FakeApplicationHandle> application =
2720 std::make_shared<FakeApplicationHandle>();
chaviwaf87b3e2019-10-01 16:59:28 -07002721 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
2722 ADISPLAY_ID_DEFAULT);
2723 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
2724 // 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 +01002725 mWindow1->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2726 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002727 mWindow1->setFrame(Rect(0, 0, 100, 100));
2728
2729 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
2730 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
Michael Wright44753b12020-07-08 13:48:11 +01002731 mWindow2->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2732 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002733 mWindow2->setFrame(Rect(100, 100, 200, 200));
2734
Arthur Hung72d8dc32020-03-28 00:48:39 +00002735 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07002736 }
2737
2738protected:
2739 sp<FakeWindowHandle> mWindow1;
2740 sp<FakeWindowHandle> mWindow2;
2741
2742 // Helper function to convert the point from screen coordinates into the window's space
2743 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07002744 vec2 vals = windowInfo->transform.transform(point.x, point.y);
2745 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07002746 }
2747
2748 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
2749 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002750 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07002751 InputEvent* event = window->consume();
2752
2753 ASSERT_NE(nullptr, event) << name.c_str()
2754 << ": consumer should have returned non-NULL event.";
2755
2756 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
2757 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
2758 << " event, got " << inputEventTypeToString(event->getType()) << " event";
2759
2760 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
2761 EXPECT_EQ(expectedAction, motionEvent.getAction());
2762
2763 for (size_t i = 0; i < points.size(); i++) {
2764 float expectedX = points[i].x;
2765 float expectedY = points[i].y;
2766
2767 EXPECT_EQ(expectedX, motionEvent.getX(i))
2768 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
2769 << ", got " << motionEvent.getX(i);
2770 EXPECT_EQ(expectedY, motionEvent.getY(i))
2771 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
2772 << ", got " << motionEvent.getY(i);
2773 }
2774 }
chaviw9eaa22c2020-07-01 16:21:27 -07002775
2776 void touchAndAssertPositions(int32_t action, std::vector<PointF> touchedPoints,
2777 std::vector<PointF> expectedPoints) {
2778 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
2779 ADISPLAY_ID_DEFAULT, touchedPoints);
2780 mDispatcher->notifyMotion(&motionArgs);
2781
2782 // Always consume from window1 since it's the window that has the InputReceiver
2783 consumeMotionEvent(mWindow1, action, expectedPoints);
2784 }
chaviwaf87b3e2019-10-01 16:59:28 -07002785};
2786
2787TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
2788 // Touch Window 1
2789 PointF touchedPoint = {10, 10};
2790 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002791 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002792
2793 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07002794 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002795
2796 // Touch Window 2
2797 touchedPoint = {150, 150};
2798 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002799 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002800}
2801
chaviw9eaa22c2020-07-01 16:21:27 -07002802TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
2803 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07002804 mWindow2->setWindowScale(0.5f, 0.5f);
2805
2806 // Touch Window 1
2807 PointF touchedPoint = {10, 10};
2808 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002809 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002810 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07002811 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002812
2813 // Touch Window 2
2814 touchedPoint = {150, 150};
2815 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002816 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
2817 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002818
chaviw9eaa22c2020-07-01 16:21:27 -07002819 // Update the transform so rotation is set
2820 mWindow2->setWindowTransform(0, -1, 1, 0);
2821 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2822 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002823}
2824
chaviw9eaa22c2020-07-01 16:21:27 -07002825TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002826 mWindow2->setWindowScale(0.5f, 0.5f);
2827
2828 // Touch Window 1
2829 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2830 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002831 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002832
2833 // Touch Window 2
2834 int32_t actionPointerDown =
2835 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002836 touchedPoints.push_back(PointF{150, 150});
2837 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2838 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002839
chaviw9eaa22c2020-07-01 16:21:27 -07002840 // Release Window 2
2841 int32_t actionPointerUp =
2842 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2843 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
2844 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002845
chaviw9eaa22c2020-07-01 16:21:27 -07002846 // Update the transform so rotation is set for Window 2
2847 mWindow2->setWindowTransform(0, -1, 1, 0);
2848 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2849 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002850}
2851
chaviw9eaa22c2020-07-01 16:21:27 -07002852TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002853 mWindow2->setWindowScale(0.5f, 0.5f);
2854
2855 // Touch Window 1
2856 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2857 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002858 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002859
2860 // Touch Window 2
2861 int32_t actionPointerDown =
2862 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002863 touchedPoints.push_back(PointF{150, 150});
2864 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002865
chaviw9eaa22c2020-07-01 16:21:27 -07002866 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002867
2868 // Move both windows
2869 touchedPoints = {{20, 20}, {175, 175}};
2870 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2871 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2872
chaviw9eaa22c2020-07-01 16:21:27 -07002873 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002874
chaviw9eaa22c2020-07-01 16:21:27 -07002875 // Release Window 2
2876 int32_t actionPointerUp =
2877 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2878 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
2879 expectedPoints.pop_back();
2880
2881 // Touch Window 2
2882 mWindow2->setWindowTransform(0, -1, 1, 0);
2883 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2884 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
2885
2886 // Move both windows
2887 touchedPoints = {{20, 20}, {175, 175}};
2888 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2889 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2890
2891 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002892}
2893
2894TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
2895 mWindow1->setWindowScale(0.5f, 0.5f);
2896
2897 // Touch Window 1
2898 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2899 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002900 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002901
2902 // Touch Window 2
2903 int32_t actionPointerDown =
2904 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002905 touchedPoints.push_back(PointF{150, 150});
2906 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002907
chaviw9eaa22c2020-07-01 16:21:27 -07002908 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002909
2910 // Move both windows
2911 touchedPoints = {{20, 20}, {175, 175}};
2912 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2913 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2914
chaviw9eaa22c2020-07-01 16:21:27 -07002915 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002916}
2917
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002918class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
2919 virtual void SetUp() override {
2920 InputDispatcherTest::SetUp();
2921
Chris Yea209fde2020-07-22 13:54:51 -07002922 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002923 mApplication->setDispatchingTimeout(20ms);
2924 mWindow =
2925 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2926 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05002927 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07002928 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002929 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2930 // window.
Michael Wright44753b12020-07-08 13:48:11 +01002931 mWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002932
2933 // Set focused application.
2934 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
2935
2936 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002937 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002938 mWindow->consumeFocusEvent(true);
2939 }
2940
2941 virtual void TearDown() override {
2942 InputDispatcherTest::TearDown();
2943 mWindow.clear();
2944 }
2945
2946protected:
Chris Yea209fde2020-07-22 13:54:51 -07002947 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002948 sp<FakeWindowHandle> mWindow;
2949 static constexpr PointF WINDOW_LOCATION = {20, 20};
2950
2951 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002952 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002953 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2954 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002955 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002956 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2957 WINDOW_LOCATION));
2958 }
2959};
2960
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002961// Send a tap and respond, which should not cause an ANR.
2962TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
2963 tapOnWindow();
2964 mWindow->consumeMotionDown();
2965 mWindow->consumeMotionUp();
2966 ASSERT_TRUE(mDispatcher->waitForIdle());
2967 mFakePolicy->assertNotifyAnrWasNotCalled();
2968}
2969
2970// Send a regular key and respond, which should not cause an ANR.
2971TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002972 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002973 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
2974 ASSERT_TRUE(mDispatcher->waitForIdle());
2975 mFakePolicy->assertNotifyAnrWasNotCalled();
2976}
2977
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05002978TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
2979 mWindow->setFocusable(false);
2980 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2981 mWindow->consumeFocusEvent(false);
2982
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002983 InputEventInjectionResult result =
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05002984 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002985 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
2986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05002987 // Key will not go to window because we have no focused window.
2988 // The 'no focused window' ANR timer should start instead.
2989
2990 // Now, the focused application goes away.
2991 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
2992 // The key should get dropped and there should be no ANR.
2993
2994 ASSERT_TRUE(mDispatcher->waitForIdle());
2995 mFakePolicy->assertNotifyAnrWasNotCalled();
2996}
2997
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002998// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002999// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
3000// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003001TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003002 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003003 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3004 WINDOW_LOCATION));
3005
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003006 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
3007 ASSERT_TRUE(sequenceNum);
3008 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003009 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003010
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003011 mWindow->finishEvent(*sequenceNum);
3012 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
3013 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003014 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003015 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003016}
3017
3018// Send a key to the app and have the app not respond right away.
3019TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
3020 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003021 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003022 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
3023 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003024 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003025 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003026 ASSERT_TRUE(mDispatcher->waitForIdle());
3027}
3028
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003029// We have a focused application, but no focused window
3030TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003031 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003032 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3033 mWindow->consumeFocusEvent(false);
3034
3035 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003036 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003037 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3038 WINDOW_LOCATION));
3039 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
3040 mDispatcher->waitForIdle();
3041 mFakePolicy->assertNotifyAnrWasNotCalled();
3042
3043 // Once a focused event arrives, we get an ANR for this application
3044 // We specify the injection timeout to be smaller than the application timeout, to ensure that
3045 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003046 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003047 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003048 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3049 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003050 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003051 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003052 ASSERT_TRUE(mDispatcher->waitForIdle());
3053}
3054
3055// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003056// Make sure that we don't notify policy twice about the same ANR.
3057TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003058 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003059 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3060 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003061
3062 // Once a focused event arrives, we get an ANR for this application
3063 // We specify the injection timeout to be smaller than the application timeout, to ensure that
3064 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003065 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003066 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003067 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3068 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003069 const std::chrono::duration appTimeout =
3070 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003071 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003072
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003073 std::this_thread::sleep_for(appTimeout);
3074 // ANR should not be raised again. It is up to policy to do that if it desires.
3075 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003076
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003077 // If we now get a focused window, the ANR should stop, but the policy handles that via
3078 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003079 ASSERT_TRUE(mDispatcher->waitForIdle());
3080}
3081
3082// We have a focused application, but no focused window
3083TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003084 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003085 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3086 mWindow->consumeFocusEvent(false);
3087
3088 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003089 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003090 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003091 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3092 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003093
3094 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003095 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003096
3097 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003098 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003099 ASSERT_TRUE(mDispatcher->waitForIdle());
3100 mWindow->assertNoEvents();
3101}
3102
3103/**
3104 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
3105 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
3106 * If we process 1 of the events, but ANR on the second event with the same timestamp,
3107 * the ANR mechanism should still work.
3108 *
3109 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
3110 * DOWN event, while not responding on the second one.
3111 */
3112TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
3113 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
3114 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3115 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
3116 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
3117 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003118 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003119
3120 // Now send ACTION_UP, with identical timestamp
3121 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3122 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
3123 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
3124 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003125 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003126
3127 // We have now sent down and up. Let's consume first event and then ANR on the second.
3128 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3129 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003130 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003131}
3132
3133// If an app is not responding to a key event, gesture monitors should continue to receive
3134// new motion events
3135TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
3136 FakeMonitorReceiver monitor =
3137 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
3138 true /*isGestureMonitor*/);
3139
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003140 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3141 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003142 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003143 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003144
3145 // Stuck on the ACTION_UP
3146 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003147 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003148
3149 // New tap will go to the gesture monitor, but not to the window
3150 tapOnWindow();
3151 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3152 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3153
3154 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
3155 mDispatcher->waitForIdle();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003156 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003157 mWindow->assertNoEvents();
3158 monitor.assertNoEvents();
3159}
3160
3161// If an app is not responding to a motion event, gesture monitors should continue to receive
3162// new motion events
3163TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
3164 FakeMonitorReceiver monitor =
3165 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
3166 true /*isGestureMonitor*/);
3167
3168 tapOnWindow();
3169 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3170 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3171
3172 mWindow->consumeMotionDown();
3173 // Stuck on the ACTION_UP
3174 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003175 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003176
3177 // New tap will go to the gesture monitor, but not to the window
3178 tapOnWindow();
3179 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3180 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3181
3182 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
3183 mDispatcher->waitForIdle();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003184 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003185 mWindow->assertNoEvents();
3186 monitor.assertNoEvents();
3187}
3188
3189// If a window is unresponsive, then you get anr. if the window later catches up and starts to
3190// process events, you don't get an anr. When the window later becomes unresponsive again, you
3191// get an ANR again.
3192// 1. tap -> block on ACTION_UP -> receive ANR
3193// 2. consume all pending events (= queue becomes healthy again)
3194// 3. tap again -> block on ACTION_UP again -> receive ANR second time
3195TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
3196 tapOnWindow();
3197
3198 mWindow->consumeMotionDown();
3199 // Block on ACTION_UP
3200 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003201 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003202 mWindow->consumeMotionUp(); // Now the connection should be healthy again
3203 mDispatcher->waitForIdle();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003204 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003205 mWindow->assertNoEvents();
3206
3207 tapOnWindow();
3208 mWindow->consumeMotionDown();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003209 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003210 mWindow->consumeMotionUp();
3211
3212 mDispatcher->waitForIdle();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003213 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
3214 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003215 mWindow->assertNoEvents();
3216}
3217
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003218// If a connection remains unresponsive for a while, make sure policy is only notified once about
3219// it.
3220TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003222 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3223 WINDOW_LOCATION));
3224
3225 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003226 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(windowTimeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003227 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003228 // 'notifyConnectionUnresponsive' should only be called once per connection
3229 mFakePolicy->assertNotifyAnrWasNotCalled();
3230 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003231 mWindow->consumeMotionDown();
3232 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
3233 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3234 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003235 mDispatcher->waitForIdle();
3236 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
3237 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003238}
3239
3240/**
3241 * If a window is processing a motion event, and then a key event comes in, the key event should
3242 * not to to the focused window until the motion is processed.
3243 *
3244 * Warning!!!
3245 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
3246 * and the injection timeout that we specify when injecting the key.
3247 * We must have the injection timeout (10ms) be smaller than
3248 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
3249 *
3250 * If that value changes, this test should also change.
3251 */
3252TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
3253 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
3254 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3255
3256 tapOnWindow();
3257 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
3258 ASSERT_TRUE(downSequenceNum);
3259 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
3260 ASSERT_TRUE(upSequenceNum);
3261 // Don't finish the events yet, and send a key
3262 // Injection will "succeed" because we will eventually give up and send the key to the focused
3263 // window even if motions are still being processed. But because the injection timeout is short,
3264 // we will receive INJECTION_TIMED_OUT as the result.
3265
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003266 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003267 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003268 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3269 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003270 // Key will not be sent to the window, yet, because the window is still processing events
3271 // and the key remains pending, waiting for the touch events to be processed
3272 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
3273 ASSERT_FALSE(keySequenceNum);
3274
3275 std::this_thread::sleep_for(500ms);
3276 // if we wait long enough though, dispatcher will give up, and still send the key
3277 // to the focused window, even though we have not yet finished the motion event
3278 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3279 mWindow->finishEvent(*downSequenceNum);
3280 mWindow->finishEvent(*upSequenceNum);
3281}
3282
3283/**
3284 * If a window is processing a motion event, and then a key event comes in, the key event should
3285 * not go to the focused window until the motion is processed.
3286 * If then a new motion comes in, then the pending key event should be going to the currently
3287 * focused window right away.
3288 */
3289TEST_F(InputDispatcherSingleWindowAnr,
3290 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
3291 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
3292 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3293
3294 tapOnWindow();
3295 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
3296 ASSERT_TRUE(downSequenceNum);
3297 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
3298 ASSERT_TRUE(upSequenceNum);
3299 // Don't finish the events yet, and send a key
3300 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003301 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003302 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003303 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003304 // At this point, key is still pending, and should not be sent to the application yet.
3305 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
3306 ASSERT_FALSE(keySequenceNum);
3307
3308 // Now tap down again. It should cause the pending key to go to the focused window right away.
3309 tapOnWindow();
3310 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
3311 // the other events yet. We can finish events in any order.
3312 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
3313 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
3314 mWindow->consumeMotionDown();
3315 mWindow->consumeMotionUp();
3316 mWindow->assertNoEvents();
3317}
3318
3319class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
3320 virtual void SetUp() override {
3321 InputDispatcherTest::SetUp();
3322
Chris Yea209fde2020-07-22 13:54:51 -07003323 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003324 mApplication->setDispatchingTimeout(10ms);
3325 mUnfocusedWindow =
3326 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
3327 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
3328 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3329 // window.
3330 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Michael Wright44753b12020-07-08 13:48:11 +01003331 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3332 InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
3333 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003334
3335 mFocusedWindow =
3336 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05003337 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003338 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01003339 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3340 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003341
3342 // Set focused application.
3343 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07003344 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003345
3346 // Expect one focus window exist in display.
3347 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003348 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003349 mFocusedWindow->consumeFocusEvent(true);
3350 }
3351
3352 virtual void TearDown() override {
3353 InputDispatcherTest::TearDown();
3354
3355 mUnfocusedWindow.clear();
3356 mFocusedWindow.clear();
3357 }
3358
3359protected:
Chris Yea209fde2020-07-22 13:54:51 -07003360 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003361 sp<FakeWindowHandle> mUnfocusedWindow;
3362 sp<FakeWindowHandle> mFocusedWindow;
3363 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
3364 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
3365 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
3366
3367 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
3368
3369 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
3370
3371private:
3372 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003374 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3375 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003376 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003377 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3378 location));
3379 }
3380};
3381
3382// If we have 2 windows that are both unresponsive, the one with the shortest timeout
3383// should be ANR'd first.
3384TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003385 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003386 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3387 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003388 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003389 mFocusedWindow->consumeMotionDown();
3390 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3391 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3392 // We consumed all events, so no ANR
3393 ASSERT_TRUE(mDispatcher->waitForIdle());
3394 mFakePolicy->assertNotifyAnrWasNotCalled();
3395
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003396 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003397 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3398 FOCUSED_WINDOW_LOCATION));
3399 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
3400 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003401
3402 const std::chrono::duration timeout =
3403 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003404 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
3405 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
3406 // sequence to make it consistent
3407 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003408 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003409 mFocusedWindow->consumeMotionDown();
3410 // This cancel is generated because the connection was unresponsive
3411 mFocusedWindow->consumeMotionCancel();
3412 mFocusedWindow->assertNoEvents();
3413 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003414 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003415 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mFocusedWindow->getToken());
3416 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003417}
3418
3419// If we have 2 windows with identical timeouts that are both unresponsive,
3420// it doesn't matter which order they should have ANR.
3421// But we should receive ANR for both.
3422TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
3423 // Set the timeout for unfocused window to match the focused window
3424 mUnfocusedWindow->setDispatchingTimeout(10ms);
3425 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3426
3427 tapOnFocusedWindow();
3428 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003429 sp<IBinder> anrConnectionToken1 = mFakePolicy->getUnresponsiveConnectionToken(10ms);
3430 sp<IBinder> anrConnectionToken2 = mFakePolicy->getUnresponsiveConnectionToken(0ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003431
3432 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003433 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
3434 mFocusedWindow->getToken() == anrConnectionToken2);
3435 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
3436 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003437
3438 ASSERT_TRUE(mDispatcher->waitForIdle());
3439 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003440
3441 mFocusedWindow->consumeMotionDown();
3442 mFocusedWindow->consumeMotionUp();
3443 mUnfocusedWindow->consumeMotionOutside();
3444
3445 sp<IBinder> responsiveToken1 = mFakePolicy->getResponsiveConnectionToken();
3446 sp<IBinder> responsiveToken2 = mFakePolicy->getResponsiveConnectionToken();
3447
3448 // Both applications should be marked as responsive, in any order
3449 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
3450 mFocusedWindow->getToken() == responsiveToken2);
3451 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
3452 mUnfocusedWindow->getToken() == responsiveToken2);
3453 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003454}
3455
3456// If a window is already not responding, the second tap on the same window should be ignored.
3457// We should also log an error to account for the dropped event (not tested here).
3458// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
3459TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
3460 tapOnFocusedWindow();
3461 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3462 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3463 // Receive the events, but don't respond
3464 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
3465 ASSERT_TRUE(downEventSequenceNum);
3466 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
3467 ASSERT_TRUE(upEventSequenceNum);
3468 const std::chrono::duration timeout =
3469 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003470 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003471
3472 // Tap once again
3473 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003474 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003475 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3476 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003477 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003478 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3479 FOCUSED_WINDOW_LOCATION));
3480 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
3481 // valid touch target
3482 mUnfocusedWindow->assertNoEvents();
3483
3484 // Consume the first tap
3485 mFocusedWindow->finishEvent(*downEventSequenceNum);
3486 mFocusedWindow->finishEvent(*upEventSequenceNum);
3487 ASSERT_TRUE(mDispatcher->waitForIdle());
3488 // The second tap did not go to the focused window
3489 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003490 // Since all events are finished, connection should be deemed healthy again
3491 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003492 mFakePolicy->assertNotifyAnrWasNotCalled();
3493}
3494
3495// If you tap outside of all windows, there will not be ANR
3496TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003497 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003498 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3499 LOCATION_OUTSIDE_ALL_WINDOWS));
3500 ASSERT_TRUE(mDispatcher->waitForIdle());
3501 mFakePolicy->assertNotifyAnrWasNotCalled();
3502}
3503
3504// Since the focused window is paused, tapping on it should not produce any events
3505TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
3506 mFocusedWindow->setPaused(true);
3507 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3508
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003509 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003510 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3511 FOCUSED_WINDOW_LOCATION));
3512
3513 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
3514 ASSERT_TRUE(mDispatcher->waitForIdle());
3515 // Should not ANR because the window is paused, and touches shouldn't go to it
3516 mFakePolicy->assertNotifyAnrWasNotCalled();
3517
3518 mFocusedWindow->assertNoEvents();
3519 mUnfocusedWindow->assertNoEvents();
3520}
3521
3522/**
3523 * If a window is processing a motion event, and then a key event comes in, the key event should
3524 * not to to the focused window until the motion is processed.
3525 * If a different window becomes focused at this time, the key should go to that window instead.
3526 *
3527 * Warning!!!
3528 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
3529 * and the injection timeout that we specify when injecting the key.
3530 * We must have the injection timeout (10ms) be smaller than
3531 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
3532 *
3533 * If that value changes, this test should also change.
3534 */
3535TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
3536 // Set a long ANR timeout to prevent it from triggering
3537 mFocusedWindow->setDispatchingTimeout(2s);
3538 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3539
3540 tapOnUnfocusedWindow();
3541 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
3542 ASSERT_TRUE(downSequenceNum);
3543 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
3544 ASSERT_TRUE(upSequenceNum);
3545 // Don't finish the events yet, and send a key
3546 // Injection will succeed because we will eventually give up and send the key to the focused
3547 // window even if motions are still being processed.
3548
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003549 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003550 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003551 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
3552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003553 // Key will not be sent to the window, yet, because the window is still processing events
3554 // and the key remains pending, waiting for the touch events to be processed
3555 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
3556 ASSERT_FALSE(keySequenceNum);
3557
3558 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07003559 mFocusedWindow->setFocusable(false);
3560 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003561 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003562 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003563
3564 // Focus events should precede the key events
3565 mUnfocusedWindow->consumeFocusEvent(true);
3566 mFocusedWindow->consumeFocusEvent(false);
3567
3568 // Finish the tap events, which should unblock dispatcher
3569 mUnfocusedWindow->finishEvent(*downSequenceNum);
3570 mUnfocusedWindow->finishEvent(*upSequenceNum);
3571
3572 // Now that all queues are cleared and no backlog in the connections, the key event
3573 // can finally go to the newly focused "mUnfocusedWindow".
3574 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3575 mFocusedWindow->assertNoEvents();
3576 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003577 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003578}
3579
3580// When the touch stream is split across 2 windows, and one of them does not respond,
3581// then ANR should be raised and the touch should be canceled for the unresponsive window.
3582// The other window should not be affected by that.
3583TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
3584 // Touch Window 1
3585 NotifyMotionArgs motionArgs =
3586 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3587 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
3588 mDispatcher->notifyMotion(&motionArgs);
3589 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3590 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3591
3592 // Touch Window 2
3593 int32_t actionPointerDown =
3594 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3595
3596 motionArgs =
3597 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3598 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
3599 mDispatcher->notifyMotion(&motionArgs);
3600
3601 const std::chrono::duration timeout =
3602 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003603 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003604
3605 mUnfocusedWindow->consumeMotionDown();
3606 mFocusedWindow->consumeMotionDown();
3607 // Focused window may or may not receive ACTION_MOVE
3608 // But it should definitely receive ACTION_CANCEL due to the ANR
3609 InputEvent* event;
3610 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
3611 ASSERT_TRUE(moveOrCancelSequenceNum);
3612 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
3613 ASSERT_NE(nullptr, event);
3614 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
3615 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
3616 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
3617 mFocusedWindow->consumeMotionCancel();
3618 } else {
3619 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
3620 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003621 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003622 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mFocusedWindow->getToken());
3623
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003624 mUnfocusedWindow->assertNoEvents();
3625 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003626 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003627}
3628
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003629/**
3630 * If we have no focused window, and a key comes in, we start the ANR timer.
3631 * The focused application should add a focused window before the timer runs out to prevent ANR.
3632 *
3633 * If the user touches another application during this time, the key should be dropped.
3634 * Next, if a new focused window comes in, without toggling the focused application,
3635 * then no ANR should occur.
3636 *
3637 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
3638 * but in some cases the policy may not update the focused application.
3639 */
3640TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
3641 std::shared_ptr<FakeApplicationHandle> focusedApplication =
3642 std::make_shared<FakeApplicationHandle>();
3643 focusedApplication->setDispatchingTimeout(60ms);
3644 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
3645 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
3646 mFocusedWindow->setFocusable(false);
3647
3648 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3649 mFocusedWindow->consumeFocusEvent(false);
3650
3651 // Send a key. The ANR timer should start because there is no focused window.
3652 // 'focusedApplication' will get blamed if this timer completes.
3653 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003654 InputEventInjectionResult result =
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003655 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003656 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
3657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003658
3659 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
3660 // then the injected touches won't cause the focused event to get dropped.
3661 // The dispatcher only checks for whether the queue should be pruned upon queueing.
3662 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
3663 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
3664 // For this test, it means that the key would get delivered to the window once it becomes
3665 // focused.
3666 std::this_thread::sleep_for(10ms);
3667
3668 // Touch unfocused window. This should force the pending key to get dropped.
3669 NotifyMotionArgs motionArgs =
3670 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3671 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
3672 mDispatcher->notifyMotion(&motionArgs);
3673
3674 // We do not consume the motion right away, because that would require dispatcher to first
3675 // process (== drop) the key event, and by that time, ANR will be raised.
3676 // Set the focused window first.
3677 mFocusedWindow->setFocusable(true);
3678 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3679 setFocusedWindow(mFocusedWindow);
3680 mFocusedWindow->consumeFocusEvent(true);
3681 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
3682 // to another application. This could be a bug / behaviour in the policy.
3683
3684 mUnfocusedWindow->consumeMotionDown();
3685
3686 ASSERT_TRUE(mDispatcher->waitForIdle());
3687 // Should not ANR because we actually have a focused window. It was just added too slowly.
3688 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
3689}
3690
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05003691// These tests ensure we cannot send touch events to a window that's positioned behind a window
3692// that has feature NO_INPUT_CHANNEL.
3693// Layout:
3694// Top (closest to user)
3695// mNoInputWindow (above all windows)
3696// mBottomWindow
3697// Bottom (furthest from user)
3698class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
3699 virtual void SetUp() override {
3700 InputDispatcherTest::SetUp();
3701
3702 mApplication = std::make_shared<FakeApplicationHandle>();
3703 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
3704 "Window without input channel", ADISPLAY_ID_DEFAULT,
3705 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
3706
3707 mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
3708 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
3709 // It's perfectly valid for this window to not have an associated input channel
3710
3711 mBottomWindow = new FakeWindowHandle(mApplication, mDispatcher, "Bottom window",
3712 ADISPLAY_ID_DEFAULT);
3713 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
3714
3715 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
3716 }
3717
3718protected:
3719 std::shared_ptr<FakeApplicationHandle> mApplication;
3720 sp<FakeWindowHandle> mNoInputWindow;
3721 sp<FakeWindowHandle> mBottomWindow;
3722};
3723
3724TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
3725 PointF touchedPoint = {10, 10};
3726
3727 NotifyMotionArgs motionArgs =
3728 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3729 ADISPLAY_ID_DEFAULT, {touchedPoint});
3730 mDispatcher->notifyMotion(&motionArgs);
3731
3732 mNoInputWindow->assertNoEvents();
3733 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
3734 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
3735 // and therefore should prevent mBottomWindow from receiving touches
3736 mBottomWindow->assertNoEvents();
3737}
3738
3739/**
3740 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
3741 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
3742 */
3743TEST_F(InputDispatcherMultiWindowOcclusionTests,
3744 NoInputChannelFeature_DropsTouchesWithValidChannel) {
3745 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
3746 "Window with input channel and NO_INPUT_CHANNEL",
3747 ADISPLAY_ID_DEFAULT);
3748
3749 mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
3750 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
3751 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
3752
3753 PointF touchedPoint = {10, 10};
3754
3755 NotifyMotionArgs motionArgs =
3756 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3757 ADISPLAY_ID_DEFAULT, {touchedPoint});
3758 mDispatcher->notifyMotion(&motionArgs);
3759
3760 mNoInputWindow->assertNoEvents();
3761 mBottomWindow->assertNoEvents();
3762}
3763
Vishnu Nair958da932020-08-21 17:12:37 -07003764class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
3765protected:
3766 std::shared_ptr<FakeApplicationHandle> mApp;
3767 sp<FakeWindowHandle> mWindow;
3768 sp<FakeWindowHandle> mMirror;
3769
3770 virtual void SetUp() override {
3771 InputDispatcherTest::SetUp();
3772 mApp = std::make_shared<FakeApplicationHandle>();
3773 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3774 mMirror = new FakeWindowHandle(mApp, mDispatcher, "TestWindowMirror", ADISPLAY_ID_DEFAULT,
3775 mWindow->getToken());
3776 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
3777 mWindow->setFocusable(true);
3778 mMirror->setFocusable(true);
3779 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3780 }
3781};
3782
3783TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
3784 // Request focus on a mirrored window
3785 setFocusedWindow(mMirror);
3786
3787 // window gets focused
3788 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3790 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003791 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
3792}
3793
3794// A focused & mirrored window remains focused only if the window and its mirror are both
3795// focusable.
3796TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
3797 setFocusedWindow(mMirror);
3798
3799 // window gets focused
3800 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003801 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3802 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003803 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003804 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3805 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003806 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3807
3808 mMirror->setFocusable(false);
3809 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3810
3811 // window loses focus since one of the windows associated with the token in not focusable
3812 mWindow->consumeFocusEvent(false);
3813
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003814 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3815 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003816 mWindow->assertNoEvents();
3817}
3818
3819// A focused & mirrored window remains focused until the window and its mirror both become
3820// invisible.
3821TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
3822 setFocusedWindow(mMirror);
3823
3824 // window gets focused
3825 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003826 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3827 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003828 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3830 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003831 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3832
3833 mMirror->setVisible(false);
3834 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3835
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3837 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003838 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3840 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003841 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3842
3843 mWindow->setVisible(false);
3844 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3845
3846 // window loses focus only after all windows associated with the token become invisible.
3847 mWindow->consumeFocusEvent(false);
3848
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003849 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3850 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003851 mWindow->assertNoEvents();
3852}
3853
3854// A focused & mirrored window remains focused until both windows are removed.
3855TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
3856 setFocusedWindow(mMirror);
3857
3858 // window gets focused
3859 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3861 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003862 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3864 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003865 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3866
3867 // single window is removed but the window token remains focused
3868 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
3869
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3871 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003872 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003873 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3874 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003875 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3876
3877 // Both windows are removed
3878 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3879 mWindow->consumeFocusEvent(false);
3880
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003881 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3882 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003883 mWindow->assertNoEvents();
3884}
3885
3886// Focus request can be pending until one window becomes visible.
3887TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
3888 // Request focus on an invisible mirror.
3889 mWindow->setVisible(false);
3890 mMirror->setVisible(false);
3891 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3892 setFocusedWindow(mMirror);
3893
3894 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07003896 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003897 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07003898
3899 mMirror->setVisible(true);
3900 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3901
3902 // window gets focused
3903 mWindow->consumeFocusEvent(true);
3904 // window gets the pending key event
3905 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3906}
Garfield Tane84e6f92019-08-29 17:28:41 -07003907} // namespace android::inputdispatcher