blob: 348e74748da358e7b4888fa447cd2e2c1ae0d0d8 [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;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000034using android::os::TouchOcclusionMode;
Michael Wright44753b12020-07-08 13:48:11 +010035using namespace android::flag_operators;
Garfield Tan1c7bc862020-01-28 13:24:04 -080036
Garfield Tane84e6f92019-08-29 17:28:41 -070037namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080038
39// An arbitrary time value.
40static const nsecs_t ARBITRARY_TIME = 1234;
41
42// An arbitrary device id.
43static const int32_t DEVICE_ID = 1;
44
Jeff Brownf086ddb2014-02-11 14:28:48 -080045// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080046static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080047
Michael Wrightd02c5b62014-02-10 15:10:22 -080048// An arbitrary injector pid / uid pair that has permission to inject events.
49static const int32_t INJECTOR_PID = 999;
50static const int32_t INJECTOR_UID = 1001;
51
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +000052// An arbitrary pid of the gesture monitor window
53static constexpr int32_t MONITOR_PID = 2001;
54
chaviwd1c23182019-12-20 18:44:56 -080055struct PointF {
56 float x;
57 float y;
58};
Michael Wrightd02c5b62014-02-10 15:10:22 -080059
Gang Wang342c9272020-01-13 13:15:04 -050060/**
61 * Return a DOWN key event with KEYCODE_A.
62 */
63static KeyEvent getTestKeyEvent() {
64 KeyEvent event;
65
Garfield Tanfbe732e2020-01-24 11:26:14 -080066 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
67 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
68 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050069 return event;
70}
71
Michael Wrightd02c5b62014-02-10 15:10:22 -080072// --- FakeInputDispatcherPolicy ---
73
74class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
75 InputDispatcherConfiguration mConfig;
76
77protected:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100078 virtual ~FakeInputDispatcherPolicy() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -080079
80public:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100081 FakeInputDispatcherPolicy() {}
Jackal Guof9696682018-10-05 12:23:23 +080082
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080083 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080084 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
85 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080086 }
87
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080088 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080089 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
90 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080091 }
92
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070093 void assertFilterInputEventWasNotCalled() {
94 std::scoped_lock lock(mLock);
95 ASSERT_EQ(nullptr, mFilteredEvent);
96 }
Michael Wrightd02c5b62014-02-10 15:10:22 -080097
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080098 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070099 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800100 ASSERT_TRUE(mConfigurationChangedTime)
101 << "Timed out waiting for configuration changed call";
102 ASSERT_EQ(*mConfigurationChangedTime, when);
103 mConfigurationChangedTime = std::nullopt;
104 }
105
106 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700107 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800108 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800109 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800110 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
111 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
112 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
113 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
114 mLastNotifySwitch = std::nullopt;
115 }
116
chaviwfd6d3512019-03-25 13:23:49 -0700117 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700118 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800119 ASSERT_EQ(touchedToken, mOnPointerDownToken);
120 mOnPointerDownToken.clear();
121 }
122
123 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700124 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800125 ASSERT_TRUE(mOnPointerDownToken == nullptr)
126 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700127 }
128
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700129 // This function must be called soon after the expected ANR timer starts,
130 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500131 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700132 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500133 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
134 std::shared_ptr<InputApplicationHandle> application;
135 { // acquire lock
136 std::unique_lock lock(mLock);
137 android::base::ScopedLockAssertion assumeLocked(mLock);
138 ASSERT_NO_FATAL_FAILURE(
139 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
140 } // release lock
141 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700142 }
143
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000144 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
145 const sp<IBinder>& expectedConnectionToken) {
146 sp<IBinder> connectionToken = getUnresponsiveWindowToken(timeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500147 ASSERT_EQ(expectedConnectionToken, connectionToken);
148 }
149
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000150 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedConnectionToken) {
151 sp<IBinder> connectionToken = getResponsiveWindowToken();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500152 ASSERT_EQ(expectedConnectionToken, connectionToken);
153 }
154
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000155 void assertNotifyMonitorUnresponsiveWasCalled(std::chrono::nanoseconds timeout) {
156 int32_t pid = getUnresponsiveMonitorPid(timeout);
157 ASSERT_EQ(MONITOR_PID, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500158 }
159
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000160 void assertNotifyMonitorResponsiveWasCalled() {
161 int32_t pid = getResponsiveMonitorPid();
162 ASSERT_EQ(MONITOR_PID, pid);
163 }
164
165 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500166 std::unique_lock lock(mLock);
167 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000168 return getAnrTokenLockedInterruptible(timeout, mAnrWindowTokens, lock);
169 }
170
171 sp<IBinder> getResponsiveWindowToken() {
172 std::unique_lock lock(mLock);
173 android::base::ScopedLockAssertion assumeLocked(mLock);
174 return getAnrTokenLockedInterruptible(0s, mResponsiveWindowTokens, lock);
175 }
176
177 int32_t getUnresponsiveMonitorPid(std::chrono::nanoseconds timeout) {
178 std::unique_lock lock(mLock);
179 android::base::ScopedLockAssertion assumeLocked(mLock);
180 return getAnrTokenLockedInterruptible(timeout, mAnrMonitorPids, lock);
181 }
182
183 int32_t getResponsiveMonitorPid() {
184 std::unique_lock lock(mLock);
185 android::base::ScopedLockAssertion assumeLocked(mLock);
186 return getAnrTokenLockedInterruptible(0s, mResponsiveMonitorPids, lock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500187 }
188
189 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
190 // for a specific container to become non-empty. When the container is non-empty, return the
191 // first entry from the container and erase it.
192 template <class T>
193 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
194 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
195 const std::chrono::time_point start = std::chrono::steady_clock::now();
196 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700197
198 // If there is an ANR, Dispatcher won't be idle because there are still events
199 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
200 // before checking if ANR was called.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500201 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
202 // to provide it some time to act. 100ms seems reasonable.
203 mNotifyAnr.wait_for(lock, timeToWait,
204 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700205 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500206 if (storage.empty()) {
207 ADD_FAILURE() << "Did not receive the ANR callback";
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000208 return {};
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700209 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700210 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
211 // the dispatcher started counting before this function was called
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700212 if (std::chrono::abs(timeout - waited) > 100ms) {
213 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
214 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
215 << "ms, but waited "
216 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
217 << "ms instead";
218 }
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500219 T token = storage.front();
220 storage.pop();
221 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700222 }
223
224 void assertNotifyAnrWasNotCalled() {
225 std::scoped_lock lock(mLock);
226 ASSERT_TRUE(mAnrApplications.empty());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000227 ASSERT_TRUE(mAnrWindowTokens.empty());
228 ASSERT_TRUE(mAnrMonitorPids.empty());
229 ASSERT_TRUE(mResponsiveWindowTokens.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500230 << "ANR was not called, but please also consume the 'connection is responsive' "
231 "signal";
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000232 ASSERT_TRUE(mResponsiveMonitorPids.empty())
233 << "Monitor ANR was not called, but please also consume the 'monitor is responsive'"
234 " signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700235 }
236
Garfield Tan1c7bc862020-01-28 13:24:04 -0800237 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
238 mConfig.keyRepeatTimeout = timeout;
239 mConfig.keyRepeatDelay = delay;
240 }
241
Prabir Pradhan99987712020-11-10 18:43:05 -0800242 void waitForSetPointerCapture(bool enabled) {
243 std::unique_lock lock(mLock);
244 base::ScopedLockAssertion assumeLocked(mLock);
245
246 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
247 [this, enabled]() REQUIRES(mLock) {
248 return mPointerCaptureEnabled &&
249 *mPointerCaptureEnabled ==
250 enabled;
251 })) {
252 FAIL() << "Timed out waiting for setPointerCapture(" << enabled << ") to be called.";
253 }
254 mPointerCaptureEnabled.reset();
255 }
256
257 void assertSetPointerCaptureNotCalled() {
258 std::unique_lock lock(mLock);
259 base::ScopedLockAssertion assumeLocked(mLock);
260
261 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
262 FAIL() << "Expected setPointerCapture(enabled) to not be called, but was called. "
263 "enabled = "
264 << *mPointerCaptureEnabled;
265 }
266 mPointerCaptureEnabled.reset();
267 }
268
Michael Wrightd02c5b62014-02-10 15:10:22 -0800269private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700270 std::mutex mLock;
271 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
272 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
273 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
274 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800275
Prabir Pradhan99987712020-11-10 18:43:05 -0800276 std::condition_variable mPointerCaptureChangedCondition;
277 std::optional<bool> mPointerCaptureEnabled GUARDED_BY(mLock);
278
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700279 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700280 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000281 std::queue<sp<IBinder>> mAnrWindowTokens GUARDED_BY(mLock);
282 std::queue<sp<IBinder>> mResponsiveWindowTokens GUARDED_BY(mLock);
283 std::queue<int32_t> mAnrMonitorPids GUARDED_BY(mLock);
284 std::queue<int32_t> mResponsiveMonitorPids GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700285 std::condition_variable mNotifyAnr;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700286
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600287 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700288 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800289 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800290 }
291
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000292 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700293 std::scoped_lock lock(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000294 mAnrWindowTokens.push(connectionToken);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700295 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500296 }
297
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000298 void notifyMonitorUnresponsive(int32_t pid, const std::string&) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500299 std::scoped_lock lock(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000300 mAnrMonitorPids.push(pid);
301 mNotifyAnr.notify_all();
302 }
303
304 void notifyWindowResponsive(const sp<IBinder>& connectionToken) override {
305 std::scoped_lock lock(mLock);
306 mResponsiveWindowTokens.push(connectionToken);
307 mNotifyAnr.notify_all();
308 }
309
310 void notifyMonitorResponsive(int32_t pid) override {
311 std::scoped_lock lock(mLock);
312 mResponsiveMonitorPids.push(pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500313 mNotifyAnr.notify_all();
314 }
315
316 void notifyNoFocusedWindowAnr(
317 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
318 std::scoped_lock lock(mLock);
319 mAnrApplications.push(applicationHandle);
320 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800321 }
322
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600323 void notifyInputChannelBroken(const sp<IBinder>&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800324
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600325 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700326
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600327 void notifyUntrustedTouch(const std::string& obscuringPackage) override {}
Chris Yef59a2f42020-10-16 12:55:26 -0700328 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
329 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
330 const std::vector<float>& values) override {}
331
332 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
333 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000334
Chris Yefb552902021-02-03 17:18:37 -0800335 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
336
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600337 void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800338 *outConfig = mConfig;
339 }
340
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600341 bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700342 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800343 switch (inputEvent->getType()) {
344 case AINPUT_EVENT_TYPE_KEY: {
345 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800346 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800347 break;
348 }
349
350 case AINPUT_EVENT_TYPE_MOTION: {
351 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800352 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800353 break;
354 }
355 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800356 return true;
357 }
358
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600359 void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800360
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600361 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800362
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600363 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800364 return 0;
365 }
366
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600367 bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800368 return false;
369 }
370
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600371 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
372 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700373 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800374 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
375 * essentially a passthrough for notifySwitch.
376 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800377 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800378 }
379
Sean Stoutb4e0a592021-02-23 07:34:53 -0800380 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800381
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600382 bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override { return false; }
Jackal Guof9696682018-10-05 12:23:23 +0800383
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600384 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700385 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700386 mOnPointerDownToken = newToken;
387 }
388
Prabir Pradhan99987712020-11-10 18:43:05 -0800389 void setPointerCapture(bool enabled) override {
390 std::scoped_lock lock(mLock);
391 mPointerCaptureEnabled = {enabled};
392 mPointerCaptureChangedCondition.notify_all();
393 }
394
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800395 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
396 int32_t displayId) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700397 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800398 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
399 ASSERT_EQ(mFilteredEvent->getType(), type);
400
401 if (type == AINPUT_EVENT_TYPE_KEY) {
402 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
403 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
404 EXPECT_EQ(keyEvent.getAction(), action);
405 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
406 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
407 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
408 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
409 EXPECT_EQ(motionEvent.getAction(), action);
410 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
411 } else {
412 FAIL() << "Unknown type: " << type;
413 }
414
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800415 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800416 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800417};
418
Michael Wrightd02c5b62014-02-10 15:10:22 -0800419// --- InputDispatcherTest ---
420
421class InputDispatcherTest : public testing::Test {
422protected:
423 sp<FakeInputDispatcherPolicy> mFakePolicy;
424 sp<InputDispatcher> mDispatcher;
425
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700426 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800427 mFakePolicy = new FakeInputDispatcherPolicy();
428 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800429 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000430 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700431 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800432 }
433
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700434 virtual void TearDown() override {
435 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800436 mFakePolicy.clear();
437 mDispatcher.clear();
438 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700439
440 /**
441 * Used for debugging when writing the test
442 */
443 void dumpDispatcherState() {
444 std::string dump;
445 mDispatcher->dump(dump);
446 std::stringstream ss(dump);
447 std::string to;
448
449 while (std::getline(ss, to, '\n')) {
450 ALOGE("%s", to.c_str());
451 }
452 }
Vishnu Nair958da932020-08-21 17:12:37 -0700453
454 void setFocusedWindow(const sp<InputWindowHandle>& window,
455 const sp<InputWindowHandle>& focusedWindow = nullptr) {
456 FocusRequest request;
457 request.token = window->getToken();
458 if (focusedWindow) {
459 request.focusedToken = focusedWindow->getToken();
460 }
461 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
462 request.displayId = window->getInfo()->displayId;
463 mDispatcher->setFocusedWindow(request);
464 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800465};
466
Michael Wrightd02c5b62014-02-10 15:10:22 -0800467TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
468 KeyEvent event;
469
470 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800471 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
472 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600473 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
474 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800475 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700476 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800477 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800478 << "Should reject key events with undefined action.";
479
480 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800481 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
482 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600483 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800484 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700485 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800486 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800487 << "Should reject key events with ACTION_MULTIPLE.";
488}
489
490TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
491 MotionEvent event;
492 PointerProperties pointerProperties[MAX_POINTERS + 1];
493 PointerCoords pointerCoords[MAX_POINTERS + 1];
494 for (int i = 0; i <= MAX_POINTERS; i++) {
495 pointerProperties[i].clear();
496 pointerProperties[i].id = i;
497 pointerCoords[i].clear();
498 }
499
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800500 // Some constants commonly used below
501 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
502 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
503 constexpr int32_t metaState = AMETA_NONE;
504 constexpr MotionClassification classification = MotionClassification::NONE;
505
chaviw9eaa22c2020-07-01 16:21:27 -0700506 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800507 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800508 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700509 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
510 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600511 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700512 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800513 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700514 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800515 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800516 << "Should reject motion events with undefined action.";
517
518 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800519 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700520 AMOTION_EVENT_ACTION_POINTER_DOWN |
521 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700522 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
523 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
524 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
525 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800526 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700527 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800528 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800529 << "Should reject motion events with pointer down index too large.";
530
Garfield Tanfbe732e2020-01-24 11:26:14 -0800531 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700532 AMOTION_EVENT_ACTION_POINTER_DOWN |
533 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700534 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
535 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
536 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
537 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800538 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700539 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800540 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800541 << "Should reject motion events with pointer down index too small.";
542
543 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800544 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700545 AMOTION_EVENT_ACTION_POINTER_UP |
546 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700547 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
548 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
549 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
550 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800551 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700552 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800553 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800554 << "Should reject motion events with pointer up index too large.";
555
Garfield Tanfbe732e2020-01-24 11:26:14 -0800556 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700557 AMOTION_EVENT_ACTION_POINTER_UP |
558 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700559 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
560 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
561 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
562 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800563 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700564 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800565 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800566 << "Should reject motion events with pointer up index too small.";
567
568 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800569 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
570 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700571 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
572 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700573 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800574 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700575 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800576 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800577 << "Should reject motion events with 0 pointers.";
578
Garfield Tanfbe732e2020-01-24 11:26:14 -0800579 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
580 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700581 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
582 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700583 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800584 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700585 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800586 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800587 << "Should reject motion events with more than MAX_POINTERS pointers.";
588
589 // Rejects motion events with invalid pointer ids.
590 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800591 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
592 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700593 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
594 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700595 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800596 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700597 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800598 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800599 << "Should reject motion events with pointer ids less than 0.";
600
601 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800602 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
603 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700604 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
605 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700606 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800607 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700608 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800609 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800610 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
611
612 // Rejects motion events with duplicate pointer ids.
613 pointerProperties[0].id = 1;
614 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800615 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
616 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700617 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
618 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700619 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800620 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700621 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800622 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800623 << "Should reject motion events with duplicate pointer ids.";
624}
625
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800626/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
627
628TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
629 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800630 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800631 mDispatcher->notifyConfigurationChanged(&args);
632 ASSERT_TRUE(mDispatcher->waitForIdle());
633
634 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
635}
636
637TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800638 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
639 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800640 mDispatcher->notifySwitch(&args);
641
642 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
643 args.policyFlags |= POLICY_FLAG_TRUSTED;
644 mFakePolicy->assertNotifySwitchWasCalled(args);
645}
646
Arthur Hungb92218b2018-08-14 12:00:21 +0800647// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700648static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700649static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
Arthur Hungb92218b2018-08-14 12:00:21 +0800650
651class FakeApplicationHandle : public InputApplicationHandle {
652public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700653 FakeApplicationHandle() {
654 mInfo.name = "Fake Application";
655 mInfo.token = new BBinder();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500656 mInfo.dispatchingTimeoutMillis =
657 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700658 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800659 virtual ~FakeApplicationHandle() {}
660
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000661 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700662
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500663 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
664 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700665 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800666};
667
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800668class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800669public:
Garfield Tan15601662020-09-22 15:32:38 -0700670 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800671 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700672 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800673 }
674
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800675 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700676 InputEvent* event;
677 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
678 if (!consumeSeq) {
679 return nullptr;
680 }
681 finishEvent(*consumeSeq);
682 return event;
683 }
684
685 /**
686 * Receive an event without acknowledging it.
687 * Return the sequence number that could later be used to send finished signal.
688 */
689 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800690 uint32_t consumeSeq;
691 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800692
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800693 std::chrono::time_point start = std::chrono::steady_clock::now();
694 status_t status = WOULD_BLOCK;
695 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800696 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800697 &event);
698 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
699 if (elapsed > 100ms) {
700 break;
701 }
702 }
703
704 if (status == WOULD_BLOCK) {
705 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700706 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800707 }
708
709 if (status != OK) {
710 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700711 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800712 }
713 if (event == nullptr) {
714 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700715 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800716 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700717 if (outEvent != nullptr) {
718 *outEvent = event;
719 }
720 return consumeSeq;
721 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800722
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700723 /**
724 * To be used together with "receiveEvent" to complete the consumption of an event.
725 */
726 void finishEvent(uint32_t consumeSeq) {
727 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
728 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800729 }
730
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000731 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
732 std::optional<int32_t> expectedDisplayId,
733 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800734 InputEvent* event = consume();
735
736 ASSERT_NE(nullptr, event) << mName.c_str()
737 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800738 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700739 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800740 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800741
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000742 if (expectedDisplayId.has_value()) {
743 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
744 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800745
Tiger Huang8664f8c2018-10-11 19:14:35 +0800746 switch (expectedEventType) {
747 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800748 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
749 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000750 if (expectedFlags.has_value()) {
751 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
752 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800753 break;
754 }
755 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800756 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
757 EXPECT_EQ(expectedAction, motionEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000758 if (expectedFlags.has_value()) {
759 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
760 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800761 break;
762 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100763 case AINPUT_EVENT_TYPE_FOCUS: {
764 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
765 }
Prabir Pradhan99987712020-11-10 18:43:05 -0800766 case AINPUT_EVENT_TYPE_CAPTURE: {
767 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
768 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800769 default: {
770 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
771 }
772 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800773 }
774
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100775 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
776 InputEvent* event = consume();
777 ASSERT_NE(nullptr, event) << mName.c_str()
778 << ": consumer should have returned non-NULL event.";
779 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
780 << "Got " << inputEventTypeToString(event->getType())
781 << " event instead of FOCUS event";
782
783 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
784 << mName.c_str() << ": event displayId should always be NONE.";
785
786 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
787 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
788 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
789 }
790
Prabir Pradhan99987712020-11-10 18:43:05 -0800791 void consumeCaptureEvent(bool hasCapture) {
792 const InputEvent* event = consume();
793 ASSERT_NE(nullptr, event) << mName.c_str()
794 << ": consumer should have returned non-NULL event.";
795 ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType())
796 << "Got " << inputEventTypeToString(event->getType())
797 << " event instead of CAPTURE event";
798
799 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
800 << mName.c_str() << ": event displayId should always be NONE.";
801
802 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
803 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
804 }
805
chaviwd1c23182019-12-20 18:44:56 -0800806 void assertNoEvents() {
807 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700808 if (event == nullptr) {
809 return;
810 }
811 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
812 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
813 ADD_FAILURE() << "Received key event "
814 << KeyEvent::actionToString(keyEvent.getAction());
815 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
816 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
817 ADD_FAILURE() << "Received motion event "
818 << MotionEvent::actionToString(motionEvent.getAction());
819 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
820 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
821 ADD_FAILURE() << "Received focus event, hasFocus = "
822 << (focusEvent.getHasFocus() ? "true" : "false");
Prabir Pradhan99987712020-11-10 18:43:05 -0800823 } else if (event->getType() == AINPUT_EVENT_TYPE_CAPTURE) {
824 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
825 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
826 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700827 }
828 FAIL() << mName.c_str()
829 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800830 }
831
832 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
833
834protected:
835 std::unique_ptr<InputConsumer> mConsumer;
836 PreallocatedInputEventFactory mEventFactory;
837
838 std::string mName;
839};
840
841class FakeWindowHandle : public InputWindowHandle {
842public:
843 static const int32_t WIDTH = 600;
844 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800845
Chris Yea209fde2020-07-22 13:54:51 -0700846 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
chaviwd1c23182019-12-20 18:44:56 -0800847 const sp<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500848 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -0800849 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500850 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -0700851 base::Result<std::unique_ptr<InputChannel>> channel =
852 dispatcher->createInputChannel(name);
853 token = (*channel)->getConnectionToken();
854 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -0800855 }
856
857 inputApplicationHandle->updateInfo();
858 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
859
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500860 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700861 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800862 mInfo.name = name;
Michael Wright44753b12020-07-08 13:48:11 +0100863 mInfo.type = InputWindowInfo::Type::APPLICATION;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500864 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000865 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -0800866 mInfo.frameLeft = 0;
867 mInfo.frameTop = 0;
868 mInfo.frameRight = WIDTH;
869 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -0700870 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -0800871 mInfo.globalScaleFactor = 1.0;
872 mInfo.touchableRegion.clear();
873 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
874 mInfo.visible = true;
Vishnu Nair47074b82020-08-14 11:54:47 -0700875 mInfo.focusable = false;
chaviwd1c23182019-12-20 18:44:56 -0800876 mInfo.hasWallpaper = false;
877 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800878 mInfo.ownerPid = INJECTOR_PID;
879 mInfo.ownerUid = INJECTOR_UID;
chaviwd1c23182019-12-20 18:44:56 -0800880 mInfo.displayId = displayId;
881 }
882
883 virtual bool updateInfo() { return true; }
884
Vishnu Nair47074b82020-08-14 11:54:47 -0700885 void setFocusable(bool focusable) { mInfo.focusable = focusable; }
chaviwd1c23182019-12-20 18:44:56 -0800886
Vishnu Nair958da932020-08-21 17:12:37 -0700887 void setVisible(bool visible) { mInfo.visible = visible; }
888
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700889 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500890 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700891 }
892
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700893 void setPaused(bool paused) { mInfo.paused = paused; }
894
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000895 void setAlpha(float alpha) { mInfo.alpha = alpha; }
896
897 void setTouchOcclusionMode(android::os::TouchOcclusionMode mode) {
898 mInfo.touchOcclusionMode = mode;
899 }
900
chaviwd1c23182019-12-20 18:44:56 -0800901 void setFrame(const Rect& frame) {
902 mInfo.frameLeft = frame.left;
903 mInfo.frameTop = frame.top;
904 mInfo.frameRight = frame.right;
905 mInfo.frameBottom = frame.bottom;
chaviw1ff3d1e2020-07-01 15:53:47 -0700906 mInfo.transform.set(frame.left, frame.top);
chaviwd1c23182019-12-20 18:44:56 -0800907 mInfo.touchableRegion.clear();
908 mInfo.addTouchableRegion(frame);
909 }
910
Michael Wright44753b12020-07-08 13:48:11 +0100911 void setFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags = flags; }
chaviwd1c23182019-12-20 18:44:56 -0800912
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500913 void setInputFeatures(InputWindowInfo::Feature features) { mInfo.inputFeatures = features; }
914
chaviw9eaa22c2020-07-01 16:21:27 -0700915 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
916 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
917 }
918
919 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -0700920
yunho.shinf4a80b82020-11-16 21:13:57 +0900921 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
922
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800923 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
924 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
925 expectedFlags);
926 }
927
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700928 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
929 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
930 }
931
Svet Ganov5d3bc372020-01-26 23:11:07 -0800932 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000933 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800934 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
935 expectedFlags);
936 }
937
938 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000939 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800940 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
941 expectedFlags);
942 }
943
944 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000945 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000946 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
947 }
948
949 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
950 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800951 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
952 expectedFlags);
953 }
954
Svet Ganov5d3bc372020-01-26 23:11:07 -0800955 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000956 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
957 int32_t expectedFlags = 0) {
958 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
959 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -0800960 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
961 }
962
963 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000964 int32_t expectedFlags = 0) {
965 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
966 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -0800967 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
968 }
969
970 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000971 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000972 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
973 expectedFlags);
974 }
975
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500976 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
977 int32_t expectedFlags = 0) {
978 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
979 expectedFlags);
980 }
981
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100982 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
983 ASSERT_NE(mInputReceiver, nullptr)
984 << "Cannot consume events from a window with no receiver";
985 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
986 }
987
Prabir Pradhan99987712020-11-10 18:43:05 -0800988 void consumeCaptureEvent(bool hasCapture) {
989 ASSERT_NE(mInputReceiver, nullptr)
990 << "Cannot consume events from a window with no receiver";
991 mInputReceiver->consumeCaptureEvent(hasCapture);
992 }
993
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000994 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
995 std::optional<int32_t> expectedDisplayId,
996 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -0800997 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
998 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
999 expectedFlags);
1000 }
1001
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001002 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001003 if (mInputReceiver == nullptr) {
1004 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1005 return std::nullopt;
1006 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001007 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001008 }
1009
1010 void finishEvent(uint32_t sequenceNum) {
1011 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1012 mInputReceiver->finishEvent(sequenceNum);
1013 }
1014
chaviwaf87b3e2019-10-01 16:59:28 -07001015 InputEvent* consume() {
1016 if (mInputReceiver == nullptr) {
1017 return nullptr;
1018 }
1019 return mInputReceiver->consume();
1020 }
1021
Arthur Hungb92218b2018-08-14 12:00:21 +08001022 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001023 if (mInputReceiver == nullptr &&
1024 mInfo.inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL)) {
1025 return; // Can't receive events if the window does not have input channel
1026 }
1027 ASSERT_NE(nullptr, mInputReceiver)
1028 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001029 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001030 }
1031
chaviwaf87b3e2019-10-01 16:59:28 -07001032 sp<IBinder> getToken() { return mInfo.token; }
1033
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001034 const std::string& getName() { return mName; }
1035
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001036 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1037 mInfo.ownerPid = ownerPid;
1038 mInfo.ownerUid = ownerUid;
1039 }
1040
chaviwd1c23182019-12-20 18:44:56 -08001041private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001042 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001043 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001044 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001045};
1046
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001047std::atomic<int32_t> FakeWindowHandle::sId{1};
1048
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001049static InputEventInjectionResult injectKey(
1050 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
1051 int32_t displayId = ADISPLAY_ID_NONE,
1052 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1053 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001054 KeyEvent event;
1055 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1056
1057 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001058 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001059 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
1060 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001061
1062 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001063 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
1064 injectionTimeout,
1065 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
Arthur Hungb92218b2018-08-14 12:00:21 +08001066}
1067
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001068static InputEventInjectionResult injectKeyDown(const sp<InputDispatcher>& dispatcher,
1069 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001070 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
1071}
1072
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001073static InputEventInjectionResult injectKeyUp(const sp<InputDispatcher>& dispatcher,
1074 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001075 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
1076}
1077
Garfield Tandf26e862020-07-01 20:18:19 -07001078class PointerBuilder {
1079public:
1080 PointerBuilder(int32_t id, int32_t toolType) {
1081 mProperties.clear();
1082 mProperties.id = id;
1083 mProperties.toolType = toolType;
1084 mCoords.clear();
1085 }
1086
1087 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1088
1089 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1090
1091 PointerBuilder& axis(int32_t axis, float value) {
1092 mCoords.setAxisValue(axis, value);
1093 return *this;
1094 }
1095
1096 PointerProperties buildProperties() const { return mProperties; }
1097
1098 PointerCoords buildCoords() const { return mCoords; }
1099
1100private:
1101 PointerProperties mProperties;
1102 PointerCoords mCoords;
1103};
1104
1105class MotionEventBuilder {
1106public:
1107 MotionEventBuilder(int32_t action, int32_t source) {
1108 mAction = action;
1109 mSource = source;
1110 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1111 }
1112
1113 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1114 mEventTime = eventTime;
1115 return *this;
1116 }
1117
1118 MotionEventBuilder& displayId(int32_t displayId) {
1119 mDisplayId = displayId;
1120 return *this;
1121 }
1122
1123 MotionEventBuilder& actionButton(int32_t actionButton) {
1124 mActionButton = actionButton;
1125 return *this;
1126 }
1127
1128 MotionEventBuilder& buttonState(int32_t actionButton) {
1129 mActionButton = actionButton;
1130 return *this;
1131 }
1132
1133 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1134 mRawXCursorPosition = rawXCursorPosition;
1135 return *this;
1136 }
1137
1138 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1139 mRawYCursorPosition = rawYCursorPosition;
1140 return *this;
1141 }
1142
1143 MotionEventBuilder& pointer(PointerBuilder pointer) {
1144 mPointers.push_back(pointer);
1145 return *this;
1146 }
1147
1148 MotionEvent build() {
1149 std::vector<PointerProperties> pointerProperties;
1150 std::vector<PointerCoords> pointerCoords;
1151 for (const PointerBuilder& pointer : mPointers) {
1152 pointerProperties.push_back(pointer.buildProperties());
1153 pointerCoords.push_back(pointer.buildCoords());
1154 }
1155
1156 // Set mouse cursor position for the most common cases to avoid boilerplate.
1157 if (mSource == AINPUT_SOURCE_MOUSE &&
1158 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1159 mPointers.size() == 1) {
1160 mRawXCursorPosition = pointerCoords[0].getX();
1161 mRawYCursorPosition = pointerCoords[0].getY();
1162 }
1163
1164 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001165 ui::Transform identityTransform;
Garfield Tandf26e862020-07-01 20:18:19 -07001166 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
1167 mAction, mActionButton, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001168 mButtonState, MotionClassification::NONE, identityTransform,
1169 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
1170 mRawYCursorPosition, mEventTime, mEventTime, mPointers.size(),
1171 pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001172
1173 return event;
1174 }
1175
1176private:
1177 int32_t mAction;
1178 int32_t mSource;
1179 nsecs_t mEventTime;
1180 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1181 int32_t mActionButton{0};
1182 int32_t mButtonState{0};
1183 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1184 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1185
1186 std::vector<PointerBuilder> mPointers;
1187};
1188
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001189static InputEventInjectionResult injectMotionEvent(
Garfield Tandf26e862020-07-01 20:18:19 -07001190 const sp<InputDispatcher>& dispatcher, const MotionEvent& event,
1191 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001192 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT) {
Garfield Tandf26e862020-07-01 20:18:19 -07001193 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
1194 injectionTimeout,
1195 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
1196}
1197
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001198static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001199 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
1200 const PointF& position,
1201 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001202 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1203 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001204 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001205 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Garfield Tandf26e862020-07-01 20:18:19 -07001206 MotionEvent event = MotionEventBuilder(action, source)
1207 .displayId(displayId)
1208 .eventTime(eventTime)
1209 .rawXCursorPosition(cursorPosition.x)
1210 .rawYCursorPosition(cursorPosition.y)
1211 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1212 .x(position.x)
1213 .y(position.y))
1214 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001215
1216 // Inject event until dispatch out.
Garfield Tandf26e862020-07-01 20:18:19 -07001217 return injectMotionEvent(dispatcher, event);
Arthur Hungb92218b2018-08-14 12:00:21 +08001218}
1219
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001220static InputEventInjectionResult injectMotionDown(const sp<InputDispatcher>& dispatcher,
1221 int32_t source, int32_t displayId,
1222 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001223 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001224}
1225
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001226static InputEventInjectionResult injectMotionUp(const sp<InputDispatcher>& dispatcher,
1227 int32_t source, int32_t displayId,
1228 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001229 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001230}
1231
Jackal Guof9696682018-10-05 12:23:23 +08001232static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1233 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1234 // Define a valid key event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001235 NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
1236 POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A,
1237 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001238
1239 return args;
1240}
1241
chaviwd1c23182019-12-20 18:44:56 -08001242static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1243 const std::vector<PointF>& points) {
1244 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001245 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1246 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1247 }
1248
chaviwd1c23182019-12-20 18:44:56 -08001249 PointerProperties pointerProperties[pointerCount];
1250 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001251
chaviwd1c23182019-12-20 18:44:56 -08001252 for (size_t i = 0; i < pointerCount; i++) {
1253 pointerProperties[i].clear();
1254 pointerProperties[i].id = i;
1255 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001256
chaviwd1c23182019-12-20 18:44:56 -08001257 pointerCoords[i].clear();
1258 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1259 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1260 }
Jackal Guof9696682018-10-05 12:23:23 +08001261
1262 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1263 // Define a valid motion event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001264 NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001265 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1266 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001267 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1268 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001269 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1270 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001271
1272 return args;
1273}
1274
chaviwd1c23182019-12-20 18:44:56 -08001275static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1276 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1277}
1278
Prabir Pradhan99987712020-11-10 18:43:05 -08001279static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(bool enabled) {
1280 return NotifyPointerCaptureChangedArgs(/* id */ 0, systemTime(SYSTEM_TIME_MONOTONIC), enabled);
1281}
1282
Arthur Hungb92218b2018-08-14 12:00:21 +08001283TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001284 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001285 sp<FakeWindowHandle> window =
1286 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001287
Arthur Hung72d8dc32020-03-28 00:48:39 +00001288 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1290 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1291 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001292
1293 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001294 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001295}
1296
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001297/**
1298 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1299 * To ensure that window receives only events that were directly inside of it, add
1300 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1301 * when finding touched windows.
1302 * This test serves as a sanity check for the next test, where setInputWindows is
1303 * called twice.
1304 */
1305TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001306 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001307 sp<FakeWindowHandle> window =
1308 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1309 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001310 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001311
1312 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001314 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1315 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001316 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001317
1318 // Window should receive motion event.
1319 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1320}
1321
1322/**
1323 * Calling setInputWindows twice, with the same info, should not cause any issues.
1324 * To ensure that window receives only events that were directly inside of it, add
1325 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1326 * when finding touched windows.
1327 */
1328TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001329 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001330 sp<FakeWindowHandle> window =
1331 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1332 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001333 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001334
1335 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1336 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001338 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1339 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001340 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001341
1342 // Window should receive motion event.
1343 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1344}
1345
Arthur Hungb92218b2018-08-14 12:00:21 +08001346// The foreground window should receive the first touch down event.
1347TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001348 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001349 sp<FakeWindowHandle> windowTop =
1350 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1351 sp<FakeWindowHandle> windowSecond =
1352 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001353
Arthur Hung72d8dc32020-03-28 00:48:39 +00001354 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001355 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1356 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1357 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001358
1359 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001360 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001361 windowSecond->assertNoEvents();
1362}
1363
Garfield Tandf26e862020-07-01 20:18:19 -07001364TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001365 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001366 sp<FakeWindowHandle> windowLeft =
1367 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1368 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001369 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001370 sp<FakeWindowHandle> windowRight =
1371 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1372 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001373 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001374
1375 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1376
1377 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
1378
1379 // Start cursor position in right window so that we can move the cursor to left window.
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_HOVER_MOVE,
1383 AINPUT_SOURCE_MOUSE)
1384 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1385 .x(900)
1386 .y(400))
1387 .build()));
1388 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1389 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1390 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1391 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1392
1393 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001394 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001395 injectMotionEvent(mDispatcher,
1396 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1397 AINPUT_SOURCE_MOUSE)
1398 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1399 .x(300)
1400 .y(400))
1401 .build()));
1402 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1403 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1404 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1405 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1406 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1407 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1408
1409 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001411 injectMotionEvent(mDispatcher,
1412 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1413 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1414 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1415 .x(300)
1416 .y(400))
1417 .build()));
1418 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1419
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001420 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001421 injectMotionEvent(mDispatcher,
1422 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1423 AINPUT_SOURCE_MOUSE)
1424 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1425 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1426 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1427 .x(300)
1428 .y(400))
1429 .build()));
1430 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1431 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1432
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001434 injectMotionEvent(mDispatcher,
1435 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1436 AINPUT_SOURCE_MOUSE)
1437 .buttonState(0)
1438 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1439 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1440 .x(300)
1441 .y(400))
1442 .build()));
1443 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1444 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1445
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001446 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001447 injectMotionEvent(mDispatcher,
1448 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1449 .buttonState(0)
1450 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1451 .x(300)
1452 .y(400))
1453 .build()));
1454 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1455
1456 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001457 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001458 injectMotionEvent(mDispatcher,
1459 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1460 AINPUT_SOURCE_MOUSE)
1461 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1462 .x(900)
1463 .y(400))
1464 .build()));
1465 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1466 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1467 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1468 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1469 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1470 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1471}
1472
1473// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
1474// directly in this test.
1475TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001476 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001477 sp<FakeWindowHandle> window =
1478 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1479 window->setFrame(Rect(0, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001480 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001481
1482 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1483
1484 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1485
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001487 injectMotionEvent(mDispatcher,
1488 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
1489 AINPUT_SOURCE_MOUSE)
1490 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1491 .x(300)
1492 .y(400))
1493 .build()));
1494 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1495 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1496
1497 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001498 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001499 injectMotionEvent(mDispatcher,
1500 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1501 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1502 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1503 .x(300)
1504 .y(400))
1505 .build()));
1506 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1507
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001508 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001509 injectMotionEvent(mDispatcher,
1510 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1511 AINPUT_SOURCE_MOUSE)
1512 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1513 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1514 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1515 .x(300)
1516 .y(400))
1517 .build()));
1518 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1519 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1520
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001521 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001522 injectMotionEvent(mDispatcher,
1523 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1524 AINPUT_SOURCE_MOUSE)
1525 .buttonState(0)
1526 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1527 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1528 .x(300)
1529 .y(400))
1530 .build()));
1531 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1532 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1533
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001534 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001535 injectMotionEvent(mDispatcher,
1536 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1537 .buttonState(0)
1538 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1539 .x(300)
1540 .y(400))
1541 .build()));
1542 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1543
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001544 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001545 injectMotionEvent(mDispatcher,
1546 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
1547 AINPUT_SOURCE_MOUSE)
1548 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1549 .x(300)
1550 .y(400))
1551 .build()));
1552 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1553 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1554}
1555
Garfield Tan00f511d2019-06-12 16:55:40 -07001556TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07001557 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07001558
1559 sp<FakeWindowHandle> windowLeft =
1560 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1561 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001562 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001563 sp<FakeWindowHandle> windowRight =
1564 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1565 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001566 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001567
1568 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1569
Arthur Hung72d8dc32020-03-28 00:48:39 +00001570 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001571
1572 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1573 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001574 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07001575 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001576 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001577 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001578 windowRight->assertNoEvents();
1579}
1580
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001581TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001582 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001583 sp<FakeWindowHandle> window =
1584 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07001585 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001586
Arthur Hung72d8dc32020-03-28 00:48:39 +00001587 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001588 setFocusedWindow(window);
1589
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001590 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001591
1592 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1593 mDispatcher->notifyKey(&keyArgs);
1594
1595 // Window should receive key down event.
1596 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1597
1598 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1599 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001600 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001601 mDispatcher->notifyDeviceReset(&args);
1602 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1603 AKEY_EVENT_FLAG_CANCELED);
1604}
1605
1606TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001607 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001608 sp<FakeWindowHandle> window =
1609 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1610
Arthur Hung72d8dc32020-03-28 00:48:39 +00001611 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001612
1613 NotifyMotionArgs motionArgs =
1614 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1615 ADISPLAY_ID_DEFAULT);
1616 mDispatcher->notifyMotion(&motionArgs);
1617
1618 // Window should receive motion down event.
1619 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1620
1621 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1622 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001623 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001624 mDispatcher->notifyDeviceReset(&args);
1625 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1626 0 /*expectedFlags*/);
1627}
1628
Svet Ganov5d3bc372020-01-26 23:11:07 -08001629TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07001630 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001631
1632 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001633 sp<FakeWindowHandle> firstWindow =
1634 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1635 sp<FakeWindowHandle> secondWindow =
1636 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001637
1638 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001639 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001640
1641 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001642 NotifyMotionArgs downMotionArgs =
1643 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1644 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001645 mDispatcher->notifyMotion(&downMotionArgs);
1646 // Only the first window should get the down event
1647 firstWindow->consumeMotionDown();
1648 secondWindow->assertNoEvents();
1649
1650 // Transfer touch focus to the second window
1651 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1652 // The first window gets cancel and the second gets down
1653 firstWindow->consumeMotionCancel();
1654 secondWindow->consumeMotionDown();
1655
1656 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001657 NotifyMotionArgs upMotionArgs =
1658 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1659 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001660 mDispatcher->notifyMotion(&upMotionArgs);
1661 // The first window gets no events and the second gets up
1662 firstWindow->assertNoEvents();
1663 secondWindow->consumeMotionUp();
1664}
1665
1666TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001667 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001668
1669 PointF touchPoint = {10, 10};
1670
1671 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001672 sp<FakeWindowHandle> firstWindow =
1673 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1674 sp<FakeWindowHandle> secondWindow =
1675 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001676
1677 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001678 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001679
1680 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001681 NotifyMotionArgs downMotionArgs =
1682 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1683 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001684 mDispatcher->notifyMotion(&downMotionArgs);
1685 // Only the first window should get the down event
1686 firstWindow->consumeMotionDown();
1687 secondWindow->assertNoEvents();
1688
1689 // Send pointer down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001690 NotifyMotionArgs pointerDownMotionArgs =
1691 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
1692 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1693 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1694 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001695 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1696 // Only the first window should get the pointer down event
1697 firstWindow->consumeMotionPointerDown(1);
1698 secondWindow->assertNoEvents();
1699
1700 // Transfer touch focus to the second window
1701 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1702 // The first window gets cancel and the second gets down and pointer down
1703 firstWindow->consumeMotionCancel();
1704 secondWindow->consumeMotionDown();
1705 secondWindow->consumeMotionPointerDown(1);
1706
1707 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001708 NotifyMotionArgs pointerUpMotionArgs =
1709 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
1710 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1711 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1712 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001713 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1714 // The first window gets nothing and the second gets pointer up
1715 firstWindow->assertNoEvents();
1716 secondWindow->consumeMotionPointerUp(1);
1717
1718 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001719 NotifyMotionArgs upMotionArgs =
1720 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1721 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001722 mDispatcher->notifyMotion(&upMotionArgs);
1723 // The first window gets nothing and the second gets up
1724 firstWindow->assertNoEvents();
1725 secondWindow->consumeMotionUp();
1726}
1727
1728TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001729 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001730
1731 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001732 sp<FakeWindowHandle> firstWindow =
1733 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001734 firstWindow->setFrame(Rect(0, 0, 600, 400));
Michael Wright44753b12020-07-08 13:48:11 +01001735 firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1736 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001737
1738 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001739 sp<FakeWindowHandle> secondWindow =
1740 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001741 secondWindow->setFrame(Rect(0, 400, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001742 secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1743 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001744
1745 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001746 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001747
1748 PointF pointInFirst = {300, 200};
1749 PointF pointInSecond = {300, 600};
1750
1751 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001752 NotifyMotionArgs firstDownMotionArgs =
1753 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1754 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001755 mDispatcher->notifyMotion(&firstDownMotionArgs);
1756 // Only the first window should get the down event
1757 firstWindow->consumeMotionDown();
1758 secondWindow->assertNoEvents();
1759
1760 // Send down to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001761 NotifyMotionArgs secondDownMotionArgs =
1762 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
1763 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1764 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1765 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001766 mDispatcher->notifyMotion(&secondDownMotionArgs);
1767 // The first window gets a move and the second a down
1768 firstWindow->consumeMotionMove();
1769 secondWindow->consumeMotionDown();
1770
1771 // Transfer touch focus to the second window
1772 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1773 // The first window gets cancel and the new gets pointer down (it already saw down)
1774 firstWindow->consumeMotionCancel();
1775 secondWindow->consumeMotionPointerDown(1);
1776
1777 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001778 NotifyMotionArgs pointerUpMotionArgs =
1779 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
1780 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1781 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1782 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001783 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1784 // The first window gets nothing and the second gets pointer up
1785 firstWindow->assertNoEvents();
1786 secondWindow->consumeMotionPointerUp(1);
1787
1788 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001789 NotifyMotionArgs upMotionArgs =
1790 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1791 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001792 mDispatcher->notifyMotion(&upMotionArgs);
1793 // The first window gets nothing and the second gets up
1794 firstWindow->assertNoEvents();
1795 secondWindow->consumeMotionUp();
1796}
1797
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001798TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001799 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001800 sp<FakeWindowHandle> window =
1801 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1802
Vishnu Nair47074b82020-08-14 11:54:47 -07001803 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001804 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001805 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001806
1807 window->consumeFocusEvent(true);
1808
1809 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1810 mDispatcher->notifyKey(&keyArgs);
1811
1812 // Window should receive key down event.
1813 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1814}
1815
1816TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001817 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001818 sp<FakeWindowHandle> window =
1819 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1820
Arthur Hung72d8dc32020-03-28 00:48:39 +00001821 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001822
1823 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1824 mDispatcher->notifyKey(&keyArgs);
1825 mDispatcher->waitForIdle();
1826
1827 window->assertNoEvents();
1828}
1829
1830// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1831TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07001832 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001833 sp<FakeWindowHandle> window =
1834 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1835
Arthur Hung72d8dc32020-03-28 00:48:39 +00001836 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001837
1838 // Send key
1839 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1840 mDispatcher->notifyKey(&keyArgs);
1841 // Send motion
1842 NotifyMotionArgs motionArgs =
1843 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1844 ADISPLAY_ID_DEFAULT);
1845 mDispatcher->notifyMotion(&motionArgs);
1846
1847 // Window should receive only the motion event
1848 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1849 window->assertNoEvents(); // Key event or focus event will not be received
1850}
1851
arthurhungea3f4fc2020-12-21 23:18:53 +08001852TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
1853 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1854
1855 // Create first non touch modal window that supports split touch
1856 sp<FakeWindowHandle> firstWindow =
1857 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1858 firstWindow->setFrame(Rect(0, 0, 600, 400));
1859 firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1860 InputWindowInfo::Flag::SPLIT_TOUCH);
1861
1862 // Create second non touch modal window that supports split touch
1863 sp<FakeWindowHandle> secondWindow =
1864 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
1865 secondWindow->setFrame(Rect(0, 400, 600, 800));
1866 secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1867 InputWindowInfo::Flag::SPLIT_TOUCH);
1868
1869 // Add the windows to the dispatcher
1870 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
1871
1872 PointF pointInFirst = {300, 200};
1873 PointF pointInSecond = {300, 600};
1874
1875 // Send down to the first window
1876 NotifyMotionArgs firstDownMotionArgs =
1877 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1878 ADISPLAY_ID_DEFAULT, {pointInFirst});
1879 mDispatcher->notifyMotion(&firstDownMotionArgs);
1880 // Only the first window should get the down event
1881 firstWindow->consumeMotionDown();
1882 secondWindow->assertNoEvents();
1883
1884 // Send down to the second window
1885 NotifyMotionArgs secondDownMotionArgs =
1886 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
1887 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1888 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1889 {pointInFirst, pointInSecond});
1890 mDispatcher->notifyMotion(&secondDownMotionArgs);
1891 // The first window gets a move and the second a down
1892 firstWindow->consumeMotionMove();
1893 secondWindow->consumeMotionDown();
1894
1895 // Send pointer cancel to the second window
1896 NotifyMotionArgs pointerUpMotionArgs =
1897 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
1898 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1899 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1900 {pointInFirst, pointInSecond});
1901 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
1902 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1903 // The first window gets move and the second gets cancel.
1904 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
1905 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
1906
1907 // Send up event.
1908 NotifyMotionArgs upMotionArgs =
1909 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1910 ADISPLAY_ID_DEFAULT);
1911 mDispatcher->notifyMotion(&upMotionArgs);
1912 // The first window gets up and the second gets nothing.
1913 firstWindow->consumeMotionUp();
1914 secondWindow->assertNoEvents();
1915}
1916
chaviwd1c23182019-12-20 18:44:56 -08001917class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001918public:
1919 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001920 int32_t displayId, bool isGestureMonitor = false) {
Garfield Tan15601662020-09-22 15:32:38 -07001921 base::Result<std::unique_ptr<InputChannel>> channel =
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +00001922 dispatcher->createInputMonitor(displayId, isGestureMonitor, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07001923 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00001924 }
1925
chaviwd1c23182019-12-20 18:44:56 -08001926 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1927
1928 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1929 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1930 expectedDisplayId, expectedFlags);
1931 }
1932
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001933 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
1934
1935 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1936
chaviwd1c23182019-12-20 18:44:56 -08001937 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1938 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1939 expectedDisplayId, expectedFlags);
1940 }
1941
1942 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1943 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1944 expectedDisplayId, expectedFlags);
1945 }
1946
1947 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1948
1949private:
1950 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001951};
1952
1953// Tests for gesture monitors
1954TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07001955 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001956 sp<FakeWindowHandle> window =
1957 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001958 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001959
chaviwd1c23182019-12-20 18:44:56 -08001960 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1961 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001962
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00001964 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001965 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00001966 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001967 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001968}
1969
1970TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07001971 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001972 sp<FakeWindowHandle> window =
1973 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1974
1975 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07001976 window->setFocusable(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001977
Arthur Hung72d8dc32020-03-28 00:48:39 +00001978 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001979 setFocusedWindow(window);
1980
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001981 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001982
chaviwd1c23182019-12-20 18:44:56 -08001983 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1984 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001985
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1987 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00001988 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001989 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001990}
1991
1992TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001993 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001994 sp<FakeWindowHandle> window =
1995 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001996 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001997
chaviwd1c23182019-12-20 18:44:56 -08001998 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1999 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00002000
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002002 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002003 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00002004 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002005 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002006
2007 window->releaseChannel();
2008
chaviwd1c23182019-12-20 18:44:56 -08002009 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00002010
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002011 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002012 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002013 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08002014 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002015}
2016
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002017TEST_F(InputDispatcherTest, UnresponsiveGestureMonitor_GetsAnr) {
2018 FakeMonitorReceiver monitor =
2019 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2020 true /*isGestureMonitor*/);
2021
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002023 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
2024 std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
2025 ASSERT_TRUE(consumeSeq);
2026
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00002027 mFakePolicy->assertNotifyMonitorUnresponsiveWasCalled(DISPATCHING_TIMEOUT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002028 monitor.finishEvent(*consumeSeq);
2029 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00002030 mFakePolicy->assertNotifyMonitorResponsiveWasCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002031}
2032
chaviw81e2bb92019-12-18 15:03:51 -08002033TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002034 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
chaviw81e2bb92019-12-18 15:03:51 -08002035 sp<FakeWindowHandle> window =
2036 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2037
Arthur Hung72d8dc32020-03-28 00:48:39 +00002038 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08002039
2040 NotifyMotionArgs motionArgs =
2041 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2042 ADISPLAY_ID_DEFAULT);
2043
2044 mDispatcher->notifyMotion(&motionArgs);
2045 // Window should receive motion down event.
2046 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2047
2048 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002049 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08002050 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
2051 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
2052 motionArgs.pointerCoords[0].getX() - 10);
2053
2054 mDispatcher->notifyMotion(&motionArgs);
2055 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
2056 0 /*expectedFlags*/);
2057}
2058
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002059/**
2060 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
2061 * the device default right away. In the test scenario, we check both the default value,
2062 * and the action of enabling / disabling.
2063 */
2064TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07002065 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002066 sp<FakeWindowHandle> window =
2067 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2068
2069 // Set focused application.
2070 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002071 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002072
2073 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00002074 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002075 setFocusedWindow(window);
2076
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002077 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2078
2079 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07002080 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002081 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002082 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
2083
2084 SCOPED_TRACE("Disable touch mode");
2085 mDispatcher->setInTouchMode(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07002086 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002087 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002088 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002089 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
2090
2091 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07002092 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002093 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002094 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
2095
2096 SCOPED_TRACE("Enable touch mode again");
2097 mDispatcher->setInTouchMode(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07002098 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002099 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002100 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002101 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2102
2103 window->assertNoEvents();
2104}
2105
Gang Wange9087892020-01-07 12:17:14 -05002106TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002107 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Gang Wange9087892020-01-07 12:17:14 -05002108 sp<FakeWindowHandle> window =
2109 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2110
2111 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002112 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05002113
Arthur Hung72d8dc32020-03-28 00:48:39 +00002114 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002115 setFocusedWindow(window);
2116
Gang Wange9087892020-01-07 12:17:14 -05002117 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2118
2119 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2120 mDispatcher->notifyKey(&keyArgs);
2121
2122 InputEvent* event = window->consume();
2123 ASSERT_NE(event, nullptr);
2124
2125 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2126 ASSERT_NE(verified, nullptr);
2127 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
2128
2129 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
2130 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
2131 ASSERT_EQ(keyArgs.source, verified->source);
2132 ASSERT_EQ(keyArgs.displayId, verified->displayId);
2133
2134 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
2135
2136 ASSERT_EQ(keyArgs.action, verifiedKey.action);
2137 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05002138 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
2139 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
2140 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
2141 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
2142 ASSERT_EQ(0, verifiedKey.repeatCount);
2143}
2144
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002145TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002146 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002147 sp<FakeWindowHandle> window =
2148 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2149
2150 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2151
Arthur Hung72d8dc32020-03-28 00:48:39 +00002152 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002153
2154 NotifyMotionArgs motionArgs =
2155 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2156 ADISPLAY_ID_DEFAULT);
2157 mDispatcher->notifyMotion(&motionArgs);
2158
2159 InputEvent* event = window->consume();
2160 ASSERT_NE(event, nullptr);
2161
2162 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2163 ASSERT_NE(verified, nullptr);
2164 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
2165
2166 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
2167 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
2168 EXPECT_EQ(motionArgs.source, verified->source);
2169 EXPECT_EQ(motionArgs.displayId, verified->displayId);
2170
2171 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
2172
2173 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
2174 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
2175 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
2176 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
2177 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
2178 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
2179 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
2180}
2181
yunho.shinf4a80b82020-11-16 21:13:57 +09002182TEST_F(InputDispatcherTest, NonPointerMotionEvent_JoystickNotTransformed) {
2183 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2184 sp<FakeWindowHandle> window =
2185 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2186 const std::string name = window->getName();
2187
2188 // Window gets transformed by offset values.
2189 window->setWindowOffset(500.0f, 500.0f);
2190
2191 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2192 window->setFocusable(true);
2193
2194 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2195
2196 // First, we set focused window so that focusedWindowHandle is not null.
2197 setFocusedWindow(window);
2198
2199 // Second, we consume focus event if it is right or wrong according to onFocusChangedLocked.
2200 window->consumeFocusEvent(true);
2201
2202 NotifyMotionArgs motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
2203 AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_DEFAULT);
2204 mDispatcher->notifyMotion(&motionArgs);
2205
2206 // Third, we consume motion event.
2207 InputEvent* event = window->consume();
2208 ASSERT_NE(event, nullptr);
2209 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
2210 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
2211 << " event, got " << inputEventTypeToString(event->getType()) << " event";
2212
2213 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
2214 EXPECT_EQ(AINPUT_EVENT_TYPE_MOTION, motionEvent.getAction());
2215
2216 float expectedX = motionArgs.pointerCoords[0].getX();
2217 float expectedY = motionArgs.pointerCoords[0].getY();
2218
2219 // Finally we test if the axis values from the final motion event are not transformed
2220 EXPECT_EQ(expectedX, motionEvent.getX(0)) << "expected " << expectedX << " for x coord of "
2221 << name.c_str() << ", got " << motionEvent.getX(0);
2222 EXPECT_EQ(expectedY, motionEvent.getY(0)) << "expected " << expectedY << " for y coord of "
2223 << name.c_str() << ", got " << motionEvent.getY(0);
2224}
2225
chaviw09c8d2d2020-08-24 15:48:26 -07002226/**
2227 * Ensure that separate calls to sign the same data are generating the same key.
2228 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
2229 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
2230 * tests.
2231 */
2232TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
2233 KeyEvent event = getTestKeyEvent();
2234 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2235
2236 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
2237 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
2238 ASSERT_EQ(hmac1, hmac2);
2239}
2240
2241/**
2242 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
2243 */
2244TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
2245 KeyEvent event = getTestKeyEvent();
2246 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2247 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
2248
2249 verifiedEvent.deviceId += 1;
2250 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2251
2252 verifiedEvent.source += 1;
2253 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2254
2255 verifiedEvent.eventTimeNanos += 1;
2256 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2257
2258 verifiedEvent.displayId += 1;
2259 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2260
2261 verifiedEvent.action += 1;
2262 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2263
2264 verifiedEvent.downTimeNanos += 1;
2265 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2266
2267 verifiedEvent.flags += 1;
2268 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2269
2270 verifiedEvent.keyCode += 1;
2271 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2272
2273 verifiedEvent.scanCode += 1;
2274 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2275
2276 verifiedEvent.metaState += 1;
2277 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2278
2279 verifiedEvent.repeatCount += 1;
2280 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2281}
2282
Vishnu Nair958da932020-08-21 17:12:37 -07002283TEST_F(InputDispatcherTest, SetFocusedWindow) {
2284 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2285 sp<FakeWindowHandle> windowTop =
2286 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2287 sp<FakeWindowHandle> windowSecond =
2288 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2289 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2290
2291 // Top window is also focusable but is not granted focus.
2292 windowTop->setFocusable(true);
2293 windowSecond->setFocusable(true);
2294 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2295 setFocusedWindow(windowSecond);
2296
2297 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002298 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2299 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002300
2301 // Focused window should receive event.
2302 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2303 windowTop->assertNoEvents();
2304}
2305
2306TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
2307 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2308 sp<FakeWindowHandle> window =
2309 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2310 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2311
2312 window->setFocusable(true);
2313 // Release channel for window is no longer valid.
2314 window->releaseChannel();
2315 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2316 setFocusedWindow(window);
2317
2318 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002319 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2320 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002321
2322 // window channel is invalid, so it should not receive any input event.
2323 window->assertNoEvents();
2324}
2325
2326TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
2327 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2328 sp<FakeWindowHandle> window =
2329 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2330 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2331
2332 // Window is not focusable.
2333 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2334 setFocusedWindow(window);
2335
2336 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002337 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2338 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002339
2340 // window is invalid, so it should not receive any input event.
2341 window->assertNoEvents();
2342}
2343
2344TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
2345 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2346 sp<FakeWindowHandle> windowTop =
2347 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2348 sp<FakeWindowHandle> windowSecond =
2349 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2350 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2351
2352 windowTop->setFocusable(true);
2353 windowSecond->setFocusable(true);
2354 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2355 setFocusedWindow(windowTop);
2356 windowTop->consumeFocusEvent(true);
2357
2358 setFocusedWindow(windowSecond, windowTop);
2359 windowSecond->consumeFocusEvent(true);
2360 windowTop->consumeFocusEvent(false);
2361
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002362 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2363 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002364
2365 // Focused window should receive event.
2366 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2367}
2368
2369TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
2370 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2371 sp<FakeWindowHandle> windowTop =
2372 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2373 sp<FakeWindowHandle> windowSecond =
2374 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2375 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2376
2377 windowTop->setFocusable(true);
2378 windowSecond->setFocusable(true);
2379 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2380 setFocusedWindow(windowSecond, windowTop);
2381
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002382 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2383 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002384
2385 // Event should be dropped.
2386 windowTop->assertNoEvents();
2387 windowSecond->assertNoEvents();
2388}
2389
2390TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
2391 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2392 sp<FakeWindowHandle> window =
2393 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2394 sp<FakeWindowHandle> previousFocusedWindow =
2395 new FakeWindowHandle(application, mDispatcher, "previousFocusedWindow",
2396 ADISPLAY_ID_DEFAULT);
2397 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2398
2399 window->setFocusable(true);
2400 previousFocusedWindow->setFocusable(true);
2401 window->setVisible(false);
2402 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
2403 setFocusedWindow(previousFocusedWindow);
2404 previousFocusedWindow->consumeFocusEvent(true);
2405
2406 // Requesting focus on invisible window takes focus from currently focused window.
2407 setFocusedWindow(window);
2408 previousFocusedWindow->consumeFocusEvent(false);
2409
2410 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07002412 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002413 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07002414
2415 // Window does not get focus event or key down.
2416 window->assertNoEvents();
2417
2418 // Window becomes visible.
2419 window->setVisible(true);
2420 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2421
2422 // Window receives focus event.
2423 window->consumeFocusEvent(true);
2424 // Focused window receives key down.
2425 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2426}
2427
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002428/**
2429 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
2430 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
2431 * of the 'slipperyEnterWindow'.
2432 *
2433 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
2434 * a way so that the touched location is no longer covered by the top window.
2435 *
2436 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
2437 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
2438 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
2439 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
2440 * with ACTION_DOWN).
2441 * Thus, the touch has been transferred from the top window into the bottom window, because the top
2442 * window moved itself away from the touched location and had Flag::SLIPPERY.
2443 *
2444 * Even though the top window moved away from the touched location, it is still obscuring the bottom
2445 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
2446 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
2447 *
2448 * In this test, we ensure that the event received by the bottom window has
2449 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
2450 */
2451TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
2452 constexpr int32_t SLIPPERY_PID = INJECTOR_PID + 1;
2453 constexpr int32_t SLIPPERY_UID = INJECTOR_UID + 1;
2454
2455 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2456 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2457
2458 sp<FakeWindowHandle> slipperyExitWindow =
2459 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2460 slipperyExitWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2461 InputWindowInfo::Flag::SLIPPERY);
2462 // Make sure this one overlaps the bottom window
2463 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
2464 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
2465 // one. Windows with the same owner are not considered to be occluding each other.
2466 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
2467
2468 sp<FakeWindowHandle> slipperyEnterWindow =
2469 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2470 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
2471
2472 mDispatcher->setInputWindows(
2473 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
2474
2475 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
2476 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2477 ADISPLAY_ID_DEFAULT, {{50, 50}});
2478 mDispatcher->notifyMotion(&args);
2479 slipperyExitWindow->consumeMotionDown();
2480 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
2481 mDispatcher->setInputWindows(
2482 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
2483
2484 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2485 ADISPLAY_ID_DEFAULT, {{51, 51}});
2486 mDispatcher->notifyMotion(&args);
2487
2488 slipperyExitWindow->consumeMotionCancel();
2489
2490 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
2491 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
2492}
2493
Garfield Tan1c7bc862020-01-28 13:24:04 -08002494class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
2495protected:
2496 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
2497 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
2498
Chris Yea209fde2020-07-22 13:54:51 -07002499 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002500 sp<FakeWindowHandle> mWindow;
2501
2502 virtual void SetUp() override {
2503 mFakePolicy = new FakeInputDispatcherPolicy();
2504 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
2505 mDispatcher = new InputDispatcher(mFakePolicy);
2506 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
2507 ASSERT_EQ(OK, mDispatcher->start());
2508
2509 setUpWindow();
2510 }
2511
2512 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07002513 mApp = std::make_shared<FakeApplicationHandle>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08002514 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2515
Vishnu Nair47074b82020-08-14 11:54:47 -07002516 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002517 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002518 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002519 mWindow->consumeFocusEvent(true);
2520 }
2521
Chris Ye2ad95392020-09-01 13:44:44 -07002522 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08002523 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07002524 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002525 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
2526 mDispatcher->notifyKey(&keyArgs);
2527
2528 // Window should receive key down event.
2529 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2530 }
2531
2532 void expectKeyRepeatOnce(int32_t repeatCount) {
2533 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
2534 InputEvent* repeatEvent = mWindow->consume();
2535 ASSERT_NE(nullptr, repeatEvent);
2536
2537 uint32_t eventType = repeatEvent->getType();
2538 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
2539
2540 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
2541 uint32_t eventAction = repeatKeyEvent->getAction();
2542 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
2543 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
2544 }
2545
Chris Ye2ad95392020-09-01 13:44:44 -07002546 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08002547 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07002548 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002549 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
2550 mDispatcher->notifyKey(&keyArgs);
2551
2552 // Window should receive key down event.
2553 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
2554 0 /*expectedFlags*/);
2555 }
2556};
2557
2558TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Chris Ye2ad95392020-09-01 13:44:44 -07002559 sendAndConsumeKeyDown(1 /* deviceId */);
2560 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2561 expectKeyRepeatOnce(repeatCount);
2562 }
2563}
2564
2565TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
2566 sendAndConsumeKeyDown(1 /* deviceId */);
2567 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2568 expectKeyRepeatOnce(repeatCount);
2569 }
2570 sendAndConsumeKeyDown(2 /* deviceId */);
2571 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08002572 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2573 expectKeyRepeatOnce(repeatCount);
2574 }
2575}
2576
2577TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Chris Ye2ad95392020-09-01 13:44:44 -07002578 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002579 expectKeyRepeatOnce(1 /*repeatCount*/);
Chris Ye2ad95392020-09-01 13:44:44 -07002580 sendAndConsumeKeyUp(1 /* deviceId */);
2581 mWindow->assertNoEvents();
2582}
2583
2584TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
2585 sendAndConsumeKeyDown(1 /* deviceId */);
2586 expectKeyRepeatOnce(1 /*repeatCount*/);
2587 sendAndConsumeKeyDown(2 /* deviceId */);
2588 expectKeyRepeatOnce(1 /*repeatCount*/);
2589 // Stale key up from device 1.
2590 sendAndConsumeKeyUp(1 /* deviceId */);
2591 // Device 2 is still down, keep repeating
2592 expectKeyRepeatOnce(2 /*repeatCount*/);
2593 expectKeyRepeatOnce(3 /*repeatCount*/);
2594 // Device 2 key up
2595 sendAndConsumeKeyUp(2 /* deviceId */);
2596 mWindow->assertNoEvents();
2597}
2598
2599TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
2600 sendAndConsumeKeyDown(1 /* deviceId */);
2601 expectKeyRepeatOnce(1 /*repeatCount*/);
2602 sendAndConsumeKeyDown(2 /* deviceId */);
2603 expectKeyRepeatOnce(1 /*repeatCount*/);
2604 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
2605 sendAndConsumeKeyUp(2 /* deviceId */);
2606 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08002607 mWindow->assertNoEvents();
2608}
2609
2610TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Chris Ye2ad95392020-09-01 13:44:44 -07002611 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002612 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2613 InputEvent* repeatEvent = mWindow->consume();
2614 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2615 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
2616 IdGenerator::getSource(repeatEvent->getId()));
2617 }
2618}
2619
2620TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Chris Ye2ad95392020-09-01 13:44:44 -07002621 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002622
2623 std::unordered_set<int32_t> idSet;
2624 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2625 InputEvent* repeatEvent = mWindow->consume();
2626 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2627 int32_t id = repeatEvent->getId();
2628 EXPECT_EQ(idSet.end(), idSet.find(id));
2629 idSet.insert(id);
2630 }
2631}
2632
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002633/* Test InputDispatcher for MultiDisplay */
2634class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
2635public:
2636 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002637 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002638 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08002639
Chris Yea209fde2020-07-22 13:54:51 -07002640 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002641 windowInPrimary =
2642 new FakeWindowHandle(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002643
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002644 // Set focus window for primary display, but focused display would be second one.
2645 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07002646 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002647 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002648 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002649 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08002650
Chris Yea209fde2020-07-22 13:54:51 -07002651 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002652 windowInSecondary =
2653 new FakeWindowHandle(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002654 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002655 // Set focus display to second one.
2656 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
2657 // Set focus window for second display.
2658 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07002659 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002660 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002661 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002662 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002663 }
2664
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002665 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002666 InputDispatcherTest::TearDown();
2667
Chris Yea209fde2020-07-22 13:54:51 -07002668 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002669 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07002670 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002671 windowInSecondary.clear();
2672 }
2673
2674protected:
Chris Yea209fde2020-07-22 13:54:51 -07002675 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002676 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07002677 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002678 sp<FakeWindowHandle> windowInSecondary;
2679};
2680
2681TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
2682 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2684 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2685 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002686 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08002687 windowInSecondary->assertNoEvents();
2688
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002689 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2691 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
2692 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08002693 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002694 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08002695}
2696
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002697TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08002698 // Test inject a key down with display id specified.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2700 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002701 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08002702 windowInSecondary->assertNoEvents();
2703
2704 // Test inject a key down without display id specified.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2706 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08002707 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002708 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08002709
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002710 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002711 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08002712
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002713 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002714 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
2715 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08002716
2717 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002718 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2719 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08002720 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002721 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08002722 windowInSecondary->assertNoEvents();
2723}
2724
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002725// Test per-display input monitors for motion event.
2726TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08002727 FakeMonitorReceiver monitorInPrimary =
2728 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2729 FakeMonitorReceiver monitorInSecondary =
2730 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002731
2732 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2734 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2735 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002736 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002737 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002738 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002739 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002740
2741 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002742 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2743 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
2744 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002745 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002746 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002747 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08002748 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002749
2750 // Test inject a non-pointer motion event.
2751 // If specific a display, it will dispatch to the focused window of particular display,
2752 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2754 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
2755 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002756 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002757 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002758 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002759 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002760}
2761
2762// Test per-display input monitors for key event.
2763TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002764 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08002765 FakeMonitorReceiver monitorInPrimary =
2766 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2767 FakeMonitorReceiver monitorInSecondary =
2768 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002769
2770 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002771 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2772 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002773 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002774 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002775 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002776 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002777}
2778
Vishnu Nair958da932020-08-21 17:12:37 -07002779TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
2780 sp<FakeWindowHandle> secondWindowInPrimary =
2781 new FakeWindowHandle(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2782 secondWindowInPrimary->setFocusable(true);
2783 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
2784 setFocusedWindow(secondWindowInPrimary);
2785 windowInPrimary->consumeFocusEvent(false);
2786 secondWindowInPrimary->consumeFocusEvent(true);
2787
2788 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2790 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002791 windowInPrimary->assertNoEvents();
2792 windowInSecondary->assertNoEvents();
2793 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2794}
2795
Jackal Guof9696682018-10-05 12:23:23 +08002796class InputFilterTest : public InputDispatcherTest {
2797protected:
2798 static constexpr int32_t SECOND_DISPLAY_ID = 1;
2799
2800 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
2801 NotifyMotionArgs motionArgs;
2802
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002803 motionArgs =
2804 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08002805 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002806 motionArgs =
2807 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08002808 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002809 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002810 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002811 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002812 } else {
2813 mFakePolicy->assertFilterInputEventWasNotCalled();
2814 }
2815 }
2816
2817 void testNotifyKey(bool expectToBeFiltered) {
2818 NotifyKeyArgs keyArgs;
2819
2820 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2821 mDispatcher->notifyKey(&keyArgs);
2822 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
2823 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002824 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002825
2826 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002827 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002828 } else {
2829 mFakePolicy->assertFilterInputEventWasNotCalled();
2830 }
2831 }
2832};
2833
2834// Test InputFilter for MotionEvent
2835TEST_F(InputFilterTest, MotionEvent_InputFilter) {
2836 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
2837 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2838 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2839
2840 // Enable InputFilter
2841 mDispatcher->setInputFilterEnabled(true);
2842 // Test touch on both primary and second display, and check if both events are filtered.
2843 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
2844 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
2845
2846 // Disable InputFilter
2847 mDispatcher->setInputFilterEnabled(false);
2848 // Test touch on both primary and second display, and check if both events aren't filtered.
2849 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2850 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2851}
2852
2853// Test InputFilter for KeyEvent
2854TEST_F(InputFilterTest, KeyEvent_InputFilter) {
2855 // Since the InputFilter is disabled by default, check if key event aren't filtered.
2856 testNotifyKey(/*expectToBeFiltered*/ false);
2857
2858 // Enable InputFilter
2859 mDispatcher->setInputFilterEnabled(true);
2860 // Send a key event, and check if it is filtered.
2861 testNotifyKey(/*expectToBeFiltered*/ true);
2862
2863 // Disable InputFilter
2864 mDispatcher->setInputFilterEnabled(false);
2865 // Send a key event, and check if it isn't filtered.
2866 testNotifyKey(/*expectToBeFiltered*/ false);
2867}
2868
chaviwfd6d3512019-03-25 13:23:49 -07002869class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002870 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07002871 InputDispatcherTest::SetUp();
2872
Chris Yea209fde2020-07-22 13:54:51 -07002873 std::shared_ptr<FakeApplicationHandle> application =
2874 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002875 mUnfocusedWindow =
2876 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002877 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
2878 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2879 // window.
Michael Wright44753b12020-07-08 13:48:11 +01002880 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002881
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002882 mFocusedWindow =
2883 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2884 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01002885 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002886
2887 // Set focused application.
2888 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002889 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07002890
2891 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002892 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002893 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002894 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07002895 }
2896
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002897 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07002898 InputDispatcherTest::TearDown();
2899
2900 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002901 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07002902 }
2903
2904protected:
2905 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002906 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002907 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07002908};
2909
2910// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2911// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
2912// the onPointerDownOutsideFocus callback.
2913TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002914 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002915 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2916 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002917 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002918 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002919
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002920 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07002921 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
2922}
2923
2924// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
2925// DOWN on the window that doesn't have focus. Ensure no window received the
2926// onPointerDownOutsideFocus callback.
2927TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002928 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002929 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002930 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002931 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002932
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002933 ASSERT_TRUE(mDispatcher->waitForIdle());
2934 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002935}
2936
2937// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
2938// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
2939TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2941 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002942 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002943
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002944 ASSERT_TRUE(mDispatcher->waitForIdle());
2945 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002946}
2947
2948// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2949// DOWN on the window that already has focus. Ensure no window received the
2950// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002951TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002952 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002953 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002954 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002955 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002956 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002957
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002958 ASSERT_TRUE(mDispatcher->waitForIdle());
2959 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002960}
2961
chaviwaf87b3e2019-10-01 16:59:28 -07002962// These tests ensures we can send touch events to a single client when there are multiple input
2963// windows that point to the same client token.
2964class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
2965 virtual void SetUp() override {
2966 InputDispatcherTest::SetUp();
2967
Chris Yea209fde2020-07-22 13:54:51 -07002968 std::shared_ptr<FakeApplicationHandle> application =
2969 std::make_shared<FakeApplicationHandle>();
chaviwaf87b3e2019-10-01 16:59:28 -07002970 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
2971 ADISPLAY_ID_DEFAULT);
2972 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
2973 // 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 +01002974 mWindow1->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2975 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002976 mWindow1->setFrame(Rect(0, 0, 100, 100));
2977
2978 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
2979 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
Michael Wright44753b12020-07-08 13:48:11 +01002980 mWindow2->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2981 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002982 mWindow2->setFrame(Rect(100, 100, 200, 200));
2983
Arthur Hung72d8dc32020-03-28 00:48:39 +00002984 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07002985 }
2986
2987protected:
2988 sp<FakeWindowHandle> mWindow1;
2989 sp<FakeWindowHandle> mWindow2;
2990
2991 // Helper function to convert the point from screen coordinates into the window's space
2992 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07002993 vec2 vals = windowInfo->transform.transform(point.x, point.y);
2994 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07002995 }
2996
2997 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
2998 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002999 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07003000 InputEvent* event = window->consume();
3001
3002 ASSERT_NE(nullptr, event) << name.c_str()
3003 << ": consumer should have returned non-NULL event.";
3004
3005 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
3006 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
3007 << " event, got " << inputEventTypeToString(event->getType()) << " event";
3008
3009 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
3010 EXPECT_EQ(expectedAction, motionEvent.getAction());
3011
3012 for (size_t i = 0; i < points.size(); i++) {
3013 float expectedX = points[i].x;
3014 float expectedY = points[i].y;
3015
3016 EXPECT_EQ(expectedX, motionEvent.getX(i))
3017 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
3018 << ", got " << motionEvent.getX(i);
3019 EXPECT_EQ(expectedY, motionEvent.getY(i))
3020 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
3021 << ", got " << motionEvent.getY(i);
3022 }
3023 }
chaviw9eaa22c2020-07-01 16:21:27 -07003024
3025 void touchAndAssertPositions(int32_t action, std::vector<PointF> touchedPoints,
3026 std::vector<PointF> expectedPoints) {
3027 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
3028 ADISPLAY_ID_DEFAULT, touchedPoints);
3029 mDispatcher->notifyMotion(&motionArgs);
3030
3031 // Always consume from window1 since it's the window that has the InputReceiver
3032 consumeMotionEvent(mWindow1, action, expectedPoints);
3033 }
chaviwaf87b3e2019-10-01 16:59:28 -07003034};
3035
3036TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
3037 // Touch Window 1
3038 PointF touchedPoint = {10, 10};
3039 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003040 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003041
3042 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07003043 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003044
3045 // Touch Window 2
3046 touchedPoint = {150, 150};
3047 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003048 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003049}
3050
chaviw9eaa22c2020-07-01 16:21:27 -07003051TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
3052 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07003053 mWindow2->setWindowScale(0.5f, 0.5f);
3054
3055 // Touch Window 1
3056 PointF touchedPoint = {10, 10};
3057 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003058 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003059 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07003060 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003061
3062 // Touch Window 2
3063 touchedPoint = {150, 150};
3064 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003065 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
3066 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003067
chaviw9eaa22c2020-07-01 16:21:27 -07003068 // Update the transform so rotation is set
3069 mWindow2->setWindowTransform(0, -1, 1, 0);
3070 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
3071 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003072}
3073
chaviw9eaa22c2020-07-01 16:21:27 -07003074TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003075 mWindow2->setWindowScale(0.5f, 0.5f);
3076
3077 // Touch Window 1
3078 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3079 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003080 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003081
3082 // Touch Window 2
3083 int32_t actionPointerDown =
3084 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003085 touchedPoints.push_back(PointF{150, 150});
3086 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3087 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003088
chaviw9eaa22c2020-07-01 16:21:27 -07003089 // Release Window 2
3090 int32_t actionPointerUp =
3091 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3092 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
3093 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003094
chaviw9eaa22c2020-07-01 16:21:27 -07003095 // Update the transform so rotation is set for Window 2
3096 mWindow2->setWindowTransform(0, -1, 1, 0);
3097 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3098 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003099}
3100
chaviw9eaa22c2020-07-01 16:21:27 -07003101TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003102 mWindow2->setWindowScale(0.5f, 0.5f);
3103
3104 // Touch Window 1
3105 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3106 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003107 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003108
3109 // Touch Window 2
3110 int32_t actionPointerDown =
3111 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003112 touchedPoints.push_back(PointF{150, 150});
3113 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003114
chaviw9eaa22c2020-07-01 16:21:27 -07003115 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003116
3117 // Move both windows
3118 touchedPoints = {{20, 20}, {175, 175}};
3119 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3120 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3121
chaviw9eaa22c2020-07-01 16:21:27 -07003122 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003123
chaviw9eaa22c2020-07-01 16:21:27 -07003124 // Release Window 2
3125 int32_t actionPointerUp =
3126 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3127 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
3128 expectedPoints.pop_back();
3129
3130 // Touch Window 2
3131 mWindow2->setWindowTransform(0, -1, 1, 0);
3132 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3133 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
3134
3135 // Move both windows
3136 touchedPoints = {{20, 20}, {175, 175}};
3137 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3138 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3139
3140 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003141}
3142
3143TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
3144 mWindow1->setWindowScale(0.5f, 0.5f);
3145
3146 // Touch Window 1
3147 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3148 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003149 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003150
3151 // Touch Window 2
3152 int32_t actionPointerDown =
3153 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003154 touchedPoints.push_back(PointF{150, 150});
3155 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003156
chaviw9eaa22c2020-07-01 16:21:27 -07003157 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003158
3159 // Move both windows
3160 touchedPoints = {{20, 20}, {175, 175}};
3161 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3162 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3163
chaviw9eaa22c2020-07-01 16:21:27 -07003164 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003165}
3166
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003167class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
3168 virtual void SetUp() override {
3169 InputDispatcherTest::SetUp();
3170
Chris Yea209fde2020-07-22 13:54:51 -07003171 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003172 mApplication->setDispatchingTimeout(20ms);
3173 mWindow =
3174 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3175 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05003176 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07003177 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003178 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3179 // window.
Michael Wright44753b12020-07-08 13:48:11 +01003180 mWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003181
3182 // Set focused application.
3183 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
3184
3185 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003186 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003187 mWindow->consumeFocusEvent(true);
3188 }
3189
3190 virtual void TearDown() override {
3191 InputDispatcherTest::TearDown();
3192 mWindow.clear();
3193 }
3194
3195protected:
Chris Yea209fde2020-07-22 13:54:51 -07003196 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003197 sp<FakeWindowHandle> mWindow;
3198 static constexpr PointF WINDOW_LOCATION = {20, 20};
3199
3200 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003202 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3203 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003204 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003205 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3206 WINDOW_LOCATION));
3207 }
3208};
3209
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003210// Send a tap and respond, which should not cause an ANR.
3211TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
3212 tapOnWindow();
3213 mWindow->consumeMotionDown();
3214 mWindow->consumeMotionUp();
3215 ASSERT_TRUE(mDispatcher->waitForIdle());
3216 mFakePolicy->assertNotifyAnrWasNotCalled();
3217}
3218
3219// Send a regular key and respond, which should not cause an ANR.
3220TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003222 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
3223 ASSERT_TRUE(mDispatcher->waitForIdle());
3224 mFakePolicy->assertNotifyAnrWasNotCalled();
3225}
3226
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05003227TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
3228 mWindow->setFocusable(false);
3229 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3230 mWindow->consumeFocusEvent(false);
3231
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003232 InputEventInjectionResult result =
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05003233 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003234 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
3235 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05003236 // Key will not go to window because we have no focused window.
3237 // The 'no focused window' ANR timer should start instead.
3238
3239 // Now, the focused application goes away.
3240 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
3241 // The key should get dropped and there should be no ANR.
3242
3243 ASSERT_TRUE(mDispatcher->waitForIdle());
3244 mFakePolicy->assertNotifyAnrWasNotCalled();
3245}
3246
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003247// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003248// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
3249// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003250TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003251 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003252 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3253 WINDOW_LOCATION));
3254
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003255 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
3256 ASSERT_TRUE(sequenceNum);
3257 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003258 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003259
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003260 mWindow->finishEvent(*sequenceNum);
3261 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
3262 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003263 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003264 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003265}
3266
3267// Send a key to the app and have the app not respond right away.
3268TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
3269 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003271 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
3272 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003273 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003274 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003275 ASSERT_TRUE(mDispatcher->waitForIdle());
3276}
3277
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003278// We have a focused application, but no focused window
3279TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003280 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003281 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3282 mWindow->consumeFocusEvent(false);
3283
3284 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003286 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3287 WINDOW_LOCATION));
3288 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
3289 mDispatcher->waitForIdle();
3290 mFakePolicy->assertNotifyAnrWasNotCalled();
3291
3292 // Once a focused event arrives, we get an ANR for this application
3293 // We specify the injection timeout to be smaller than the application timeout, to ensure that
3294 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003295 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003296 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003297 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3298 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003299 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003300 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003301 ASSERT_TRUE(mDispatcher->waitForIdle());
3302}
3303
3304// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003305// Make sure that we don't notify policy twice about the same ANR.
3306TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003307 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003308 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3309 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003310
3311 // Once a focused event arrives, we get an ANR for this application
3312 // We specify the injection timeout to be smaller than the application timeout, to ensure that
3313 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003314 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003315 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003316 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3317 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003318 const std::chrono::duration appTimeout =
3319 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003320 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003321
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003322 std::this_thread::sleep_for(appTimeout);
3323 // ANR should not be raised again. It is up to policy to do that if it desires.
3324 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003325
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003326 // If we now get a focused window, the ANR should stop, but the policy handles that via
3327 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003328 ASSERT_TRUE(mDispatcher->waitForIdle());
3329}
3330
3331// We have a focused application, but no focused window
3332TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003333 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003334 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3335 mWindow->consumeFocusEvent(false);
3336
3337 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003338 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003339 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003340 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3341 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003342
3343 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003344 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003345
3346 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003347 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003348 ASSERT_TRUE(mDispatcher->waitForIdle());
3349 mWindow->assertNoEvents();
3350}
3351
3352/**
3353 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
3354 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
3355 * If we process 1 of the events, but ANR on the second event with the same timestamp,
3356 * the ANR mechanism should still work.
3357 *
3358 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
3359 * DOWN event, while not responding on the second one.
3360 */
3361TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
3362 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
3363 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3364 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
3365 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
3366 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003367 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003368
3369 // Now send ACTION_UP, with identical timestamp
3370 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3371 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
3372 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
3373 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003374 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003375
3376 // We have now sent down and up. Let's consume first event and then ANR on the second.
3377 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3378 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003379 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003380}
3381
3382// If an app is not responding to a key event, gesture monitors should continue to receive
3383// new motion events
3384TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
3385 FakeMonitorReceiver monitor =
3386 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
3387 true /*isGestureMonitor*/);
3388
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003389 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3390 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003391 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003393
3394 // Stuck on the ACTION_UP
3395 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003396 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003397
3398 // New tap will go to the gesture monitor, but not to the window
3399 tapOnWindow();
3400 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3401 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3402
3403 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
3404 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003405 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003406 mWindow->assertNoEvents();
3407 monitor.assertNoEvents();
3408}
3409
3410// If an app is not responding to a motion event, gesture monitors should continue to receive
3411// new motion events
3412TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
3413 FakeMonitorReceiver monitor =
3414 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
3415 true /*isGestureMonitor*/);
3416
3417 tapOnWindow();
3418 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3419 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3420
3421 mWindow->consumeMotionDown();
3422 // Stuck on the ACTION_UP
3423 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003424 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003425
3426 // New tap will go to the gesture monitor, but not to the window
3427 tapOnWindow();
3428 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3429 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3430
3431 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
3432 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003433 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003434 mWindow->assertNoEvents();
3435 monitor.assertNoEvents();
3436}
3437
3438// If a window is unresponsive, then you get anr. if the window later catches up and starts to
3439// process events, you don't get an anr. When the window later becomes unresponsive again, you
3440// get an ANR again.
3441// 1. tap -> block on ACTION_UP -> receive ANR
3442// 2. consume all pending events (= queue becomes healthy again)
3443// 3. tap again -> block on ACTION_UP again -> receive ANR second time
3444TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
3445 tapOnWindow();
3446
3447 mWindow->consumeMotionDown();
3448 // Block on ACTION_UP
3449 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003450 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003451 mWindow->consumeMotionUp(); // Now the connection should be healthy again
3452 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003453 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003454 mWindow->assertNoEvents();
3455
3456 tapOnWindow();
3457 mWindow->consumeMotionDown();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003458 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003459 mWindow->consumeMotionUp();
3460
3461 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003462 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003463 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003464 mWindow->assertNoEvents();
3465}
3466
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003467// If a connection remains unresponsive for a while, make sure policy is only notified once about
3468// it.
3469TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003470 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003471 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3472 WINDOW_LOCATION));
3473
3474 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003475 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003476 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003477 // 'notifyConnectionUnresponsive' should only be called once per connection
3478 mFakePolicy->assertNotifyAnrWasNotCalled();
3479 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003480 mWindow->consumeMotionDown();
3481 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
3482 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3483 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003484 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003485 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003486 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003487}
3488
3489/**
3490 * If a window is processing a motion event, and then a key event comes in, the key event should
3491 * not to to the focused window until the motion is processed.
3492 *
3493 * Warning!!!
3494 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
3495 * and the injection timeout that we specify when injecting the key.
3496 * We must have the injection timeout (10ms) be smaller than
3497 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
3498 *
3499 * If that value changes, this test should also change.
3500 */
3501TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
3502 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
3503 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3504
3505 tapOnWindow();
3506 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
3507 ASSERT_TRUE(downSequenceNum);
3508 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
3509 ASSERT_TRUE(upSequenceNum);
3510 // Don't finish the events yet, and send a key
3511 // Injection will "succeed" because we will eventually give up and send the key to the focused
3512 // window even if motions are still being processed. But because the injection timeout is short,
3513 // we will receive INJECTION_TIMED_OUT as the result.
3514
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003515 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003516 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003517 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3518 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003519 // Key will not be sent to the window, yet, because the window is still processing events
3520 // and the key remains pending, waiting for the touch events to be processed
3521 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
3522 ASSERT_FALSE(keySequenceNum);
3523
3524 std::this_thread::sleep_for(500ms);
3525 // if we wait long enough though, dispatcher will give up, and still send the key
3526 // to the focused window, even though we have not yet finished the motion event
3527 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3528 mWindow->finishEvent(*downSequenceNum);
3529 mWindow->finishEvent(*upSequenceNum);
3530}
3531
3532/**
3533 * If a window is processing a motion event, and then a key event comes in, the key event should
3534 * not go to the focused window until the motion is processed.
3535 * If then a new motion comes in, then the pending key event should be going to the currently
3536 * focused window right away.
3537 */
3538TEST_F(InputDispatcherSingleWindowAnr,
3539 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
3540 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
3541 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3542
3543 tapOnWindow();
3544 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
3545 ASSERT_TRUE(downSequenceNum);
3546 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
3547 ASSERT_TRUE(upSequenceNum);
3548 // Don't finish the events yet, and send a key
3549 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003550 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003551 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003552 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003553 // At this point, key is still pending, and should not be sent to the application yet.
3554 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
3555 ASSERT_FALSE(keySequenceNum);
3556
3557 // Now tap down again. It should cause the pending key to go to the focused window right away.
3558 tapOnWindow();
3559 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
3560 // the other events yet. We can finish events in any order.
3561 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
3562 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
3563 mWindow->consumeMotionDown();
3564 mWindow->consumeMotionUp();
3565 mWindow->assertNoEvents();
3566}
3567
3568class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
3569 virtual void SetUp() override {
3570 InputDispatcherTest::SetUp();
3571
Chris Yea209fde2020-07-22 13:54:51 -07003572 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003573 mApplication->setDispatchingTimeout(10ms);
3574 mUnfocusedWindow =
3575 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
3576 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
3577 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3578 // window.
3579 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Michael Wright44753b12020-07-08 13:48:11 +01003580 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3581 InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
3582 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003583
3584 mFocusedWindow =
3585 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05003586 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003587 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01003588 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3589 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003590
3591 // Set focused application.
3592 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07003593 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003594
3595 // Expect one focus window exist in display.
3596 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003597 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003598 mFocusedWindow->consumeFocusEvent(true);
3599 }
3600
3601 virtual void TearDown() override {
3602 InputDispatcherTest::TearDown();
3603
3604 mUnfocusedWindow.clear();
3605 mFocusedWindow.clear();
3606 }
3607
3608protected:
Chris Yea209fde2020-07-22 13:54:51 -07003609 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003610 sp<FakeWindowHandle> mUnfocusedWindow;
3611 sp<FakeWindowHandle> mFocusedWindow;
3612 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
3613 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
3614 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
3615
3616 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
3617
3618 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
3619
3620private:
3621 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003623 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3624 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003626 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3627 location));
3628 }
3629};
3630
3631// If we have 2 windows that are both unresponsive, the one with the shortest timeout
3632// should be ANR'd first.
3633TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003635 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3636 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003637 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003638 mFocusedWindow->consumeMotionDown();
3639 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3640 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3641 // We consumed all events, so no ANR
3642 ASSERT_TRUE(mDispatcher->waitForIdle());
3643 mFakePolicy->assertNotifyAnrWasNotCalled();
3644
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003645 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003646 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3647 FOCUSED_WINDOW_LOCATION));
3648 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
3649 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003650
3651 const std::chrono::duration timeout =
3652 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003653 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003654 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
3655 // sequence to make it consistent
3656 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003657 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003658 mFocusedWindow->consumeMotionDown();
3659 // This cancel is generated because the connection was unresponsive
3660 mFocusedWindow->consumeMotionCancel();
3661 mFocusedWindow->assertNoEvents();
3662 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003663 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003664 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003665 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003666}
3667
3668// If we have 2 windows with identical timeouts that are both unresponsive,
3669// it doesn't matter which order they should have ANR.
3670// But we should receive ANR for both.
3671TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
3672 // Set the timeout for unfocused window to match the focused window
3673 mUnfocusedWindow->setDispatchingTimeout(10ms);
3674 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3675
3676 tapOnFocusedWindow();
3677 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003678 sp<IBinder> anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms);
3679 sp<IBinder> anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003680
3681 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003682 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
3683 mFocusedWindow->getToken() == anrConnectionToken2);
3684 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
3685 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003686
3687 ASSERT_TRUE(mDispatcher->waitForIdle());
3688 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003689
3690 mFocusedWindow->consumeMotionDown();
3691 mFocusedWindow->consumeMotionUp();
3692 mUnfocusedWindow->consumeMotionOutside();
3693
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003694 sp<IBinder> responsiveToken1 = mFakePolicy->getResponsiveWindowToken();
3695 sp<IBinder> responsiveToken2 = mFakePolicy->getResponsiveWindowToken();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003696
3697 // Both applications should be marked as responsive, in any order
3698 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
3699 mFocusedWindow->getToken() == responsiveToken2);
3700 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
3701 mUnfocusedWindow->getToken() == responsiveToken2);
3702 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003703}
3704
3705// If a window is already not responding, the second tap on the same window should be ignored.
3706// We should also log an error to account for the dropped event (not tested here).
3707// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
3708TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
3709 tapOnFocusedWindow();
3710 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3711 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3712 // Receive the events, but don't respond
3713 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
3714 ASSERT_TRUE(downEventSequenceNum);
3715 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
3716 ASSERT_TRUE(upEventSequenceNum);
3717 const std::chrono::duration timeout =
3718 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003719 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003720
3721 // Tap once again
3722 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003723 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003724 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3725 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003726 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003727 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3728 FOCUSED_WINDOW_LOCATION));
3729 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
3730 // valid touch target
3731 mUnfocusedWindow->assertNoEvents();
3732
3733 // Consume the first tap
3734 mFocusedWindow->finishEvent(*downEventSequenceNum);
3735 mFocusedWindow->finishEvent(*upEventSequenceNum);
3736 ASSERT_TRUE(mDispatcher->waitForIdle());
3737 // The second tap did not go to the focused window
3738 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003739 // Since all events are finished, connection should be deemed healthy again
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003740 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003741 mFakePolicy->assertNotifyAnrWasNotCalled();
3742}
3743
3744// If you tap outside of all windows, there will not be ANR
3745TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003746 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003747 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3748 LOCATION_OUTSIDE_ALL_WINDOWS));
3749 ASSERT_TRUE(mDispatcher->waitForIdle());
3750 mFakePolicy->assertNotifyAnrWasNotCalled();
3751}
3752
3753// Since the focused window is paused, tapping on it should not produce any events
3754TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
3755 mFocusedWindow->setPaused(true);
3756 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3757
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003758 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003759 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3760 FOCUSED_WINDOW_LOCATION));
3761
3762 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
3763 ASSERT_TRUE(mDispatcher->waitForIdle());
3764 // Should not ANR because the window is paused, and touches shouldn't go to it
3765 mFakePolicy->assertNotifyAnrWasNotCalled();
3766
3767 mFocusedWindow->assertNoEvents();
3768 mUnfocusedWindow->assertNoEvents();
3769}
3770
3771/**
3772 * If a window is processing a motion event, and then a key event comes in, the key event should
3773 * not to to the focused window until the motion is processed.
3774 * If a different window becomes focused at this time, the key should go to that window instead.
3775 *
3776 * Warning!!!
3777 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
3778 * and the injection timeout that we specify when injecting the key.
3779 * We must have the injection timeout (10ms) be smaller than
3780 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
3781 *
3782 * If that value changes, this test should also change.
3783 */
3784TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
3785 // Set a long ANR timeout to prevent it from triggering
3786 mFocusedWindow->setDispatchingTimeout(2s);
3787 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3788
3789 tapOnUnfocusedWindow();
3790 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
3791 ASSERT_TRUE(downSequenceNum);
3792 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
3793 ASSERT_TRUE(upSequenceNum);
3794 // Don't finish the events yet, and send a key
3795 // Injection will succeed because we will eventually give up and send the key to the focused
3796 // window even if motions are still being processed.
3797
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003798 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003799 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003800 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
3801 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003802 // Key will not be sent to the window, yet, because the window is still processing events
3803 // and the key remains pending, waiting for the touch events to be processed
3804 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
3805 ASSERT_FALSE(keySequenceNum);
3806
3807 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07003808 mFocusedWindow->setFocusable(false);
3809 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003810 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003811 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003812
3813 // Focus events should precede the key events
3814 mUnfocusedWindow->consumeFocusEvent(true);
3815 mFocusedWindow->consumeFocusEvent(false);
3816
3817 // Finish the tap events, which should unblock dispatcher
3818 mUnfocusedWindow->finishEvent(*downSequenceNum);
3819 mUnfocusedWindow->finishEvent(*upSequenceNum);
3820
3821 // Now that all queues are cleared and no backlog in the connections, the key event
3822 // can finally go to the newly focused "mUnfocusedWindow".
3823 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3824 mFocusedWindow->assertNoEvents();
3825 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003826 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003827}
3828
3829// When the touch stream is split across 2 windows, and one of them does not respond,
3830// then ANR should be raised and the touch should be canceled for the unresponsive window.
3831// The other window should not be affected by that.
3832TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
3833 // Touch Window 1
3834 NotifyMotionArgs motionArgs =
3835 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3836 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
3837 mDispatcher->notifyMotion(&motionArgs);
3838 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3839 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3840
3841 // Touch Window 2
3842 int32_t actionPointerDown =
3843 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3844
3845 motionArgs =
3846 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3847 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
3848 mDispatcher->notifyMotion(&motionArgs);
3849
3850 const std::chrono::duration timeout =
3851 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003852 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003853
3854 mUnfocusedWindow->consumeMotionDown();
3855 mFocusedWindow->consumeMotionDown();
3856 // Focused window may or may not receive ACTION_MOVE
3857 // But it should definitely receive ACTION_CANCEL due to the ANR
3858 InputEvent* event;
3859 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
3860 ASSERT_TRUE(moveOrCancelSequenceNum);
3861 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
3862 ASSERT_NE(nullptr, event);
3863 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
3864 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
3865 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
3866 mFocusedWindow->consumeMotionCancel();
3867 } else {
3868 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
3869 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003870 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003871 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003872
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003873 mUnfocusedWindow->assertNoEvents();
3874 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003875 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003876}
3877
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003878/**
3879 * If we have no focused window, and a key comes in, we start the ANR timer.
3880 * The focused application should add a focused window before the timer runs out to prevent ANR.
3881 *
3882 * If the user touches another application during this time, the key should be dropped.
3883 * Next, if a new focused window comes in, without toggling the focused application,
3884 * then no ANR should occur.
3885 *
3886 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
3887 * but in some cases the policy may not update the focused application.
3888 */
3889TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
3890 std::shared_ptr<FakeApplicationHandle> focusedApplication =
3891 std::make_shared<FakeApplicationHandle>();
3892 focusedApplication->setDispatchingTimeout(60ms);
3893 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
3894 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
3895 mFocusedWindow->setFocusable(false);
3896
3897 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3898 mFocusedWindow->consumeFocusEvent(false);
3899
3900 // Send a key. The ANR timer should start because there is no focused window.
3901 // 'focusedApplication' will get blamed if this timer completes.
3902 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003903 InputEventInjectionResult result =
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003904 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003905 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
3906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003907
3908 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
3909 // then the injected touches won't cause the focused event to get dropped.
3910 // The dispatcher only checks for whether the queue should be pruned upon queueing.
3911 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
3912 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
3913 // For this test, it means that the key would get delivered to the window once it becomes
3914 // focused.
3915 std::this_thread::sleep_for(10ms);
3916
3917 // Touch unfocused window. This should force the pending key to get dropped.
3918 NotifyMotionArgs motionArgs =
3919 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3920 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
3921 mDispatcher->notifyMotion(&motionArgs);
3922
3923 // We do not consume the motion right away, because that would require dispatcher to first
3924 // process (== drop) the key event, and by that time, ANR will be raised.
3925 // Set the focused window first.
3926 mFocusedWindow->setFocusable(true);
3927 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3928 setFocusedWindow(mFocusedWindow);
3929 mFocusedWindow->consumeFocusEvent(true);
3930 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
3931 // to another application. This could be a bug / behaviour in the policy.
3932
3933 mUnfocusedWindow->consumeMotionDown();
3934
3935 ASSERT_TRUE(mDispatcher->waitForIdle());
3936 // Should not ANR because we actually have a focused window. It was just added too slowly.
3937 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
3938}
3939
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05003940// These tests ensure we cannot send touch events to a window that's positioned behind a window
3941// that has feature NO_INPUT_CHANNEL.
3942// Layout:
3943// Top (closest to user)
3944// mNoInputWindow (above all windows)
3945// mBottomWindow
3946// Bottom (furthest from user)
3947class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
3948 virtual void SetUp() override {
3949 InputDispatcherTest::SetUp();
3950
3951 mApplication = std::make_shared<FakeApplicationHandle>();
3952 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
3953 "Window without input channel", ADISPLAY_ID_DEFAULT,
3954 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
3955
3956 mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
3957 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
3958 // It's perfectly valid for this window to not have an associated input channel
3959
3960 mBottomWindow = new FakeWindowHandle(mApplication, mDispatcher, "Bottom window",
3961 ADISPLAY_ID_DEFAULT);
3962 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
3963
3964 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
3965 }
3966
3967protected:
3968 std::shared_ptr<FakeApplicationHandle> mApplication;
3969 sp<FakeWindowHandle> mNoInputWindow;
3970 sp<FakeWindowHandle> mBottomWindow;
3971};
3972
3973TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
3974 PointF touchedPoint = {10, 10};
3975
3976 NotifyMotionArgs motionArgs =
3977 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3978 ADISPLAY_ID_DEFAULT, {touchedPoint});
3979 mDispatcher->notifyMotion(&motionArgs);
3980
3981 mNoInputWindow->assertNoEvents();
3982 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
3983 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
3984 // and therefore should prevent mBottomWindow from receiving touches
3985 mBottomWindow->assertNoEvents();
3986}
3987
3988/**
3989 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
3990 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
3991 */
3992TEST_F(InputDispatcherMultiWindowOcclusionTests,
3993 NoInputChannelFeature_DropsTouchesWithValidChannel) {
3994 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
3995 "Window with input channel and NO_INPUT_CHANNEL",
3996 ADISPLAY_ID_DEFAULT);
3997
3998 mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
3999 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
4000 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
4001
4002 PointF touchedPoint = {10, 10};
4003
4004 NotifyMotionArgs motionArgs =
4005 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4006 ADISPLAY_ID_DEFAULT, {touchedPoint});
4007 mDispatcher->notifyMotion(&motionArgs);
4008
4009 mNoInputWindow->assertNoEvents();
4010 mBottomWindow->assertNoEvents();
4011}
4012
Vishnu Nair958da932020-08-21 17:12:37 -07004013class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
4014protected:
4015 std::shared_ptr<FakeApplicationHandle> mApp;
4016 sp<FakeWindowHandle> mWindow;
4017 sp<FakeWindowHandle> mMirror;
4018
4019 virtual void SetUp() override {
4020 InputDispatcherTest::SetUp();
4021 mApp = std::make_shared<FakeApplicationHandle>();
4022 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
4023 mMirror = new FakeWindowHandle(mApp, mDispatcher, "TestWindowMirror", ADISPLAY_ID_DEFAULT,
4024 mWindow->getToken());
4025 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
4026 mWindow->setFocusable(true);
4027 mMirror->setFocusable(true);
4028 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4029 }
4030};
4031
4032TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
4033 // Request focus on a mirrored window
4034 setFocusedWindow(mMirror);
4035
4036 // window gets focused
4037 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4039 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004040 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
4041}
4042
4043// A focused & mirrored window remains focused only if the window and its mirror are both
4044// focusable.
4045TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
4046 setFocusedWindow(mMirror);
4047
4048 // window gets focused
4049 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4051 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004052 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004053 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4054 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004055 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4056
4057 mMirror->setFocusable(false);
4058 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4059
4060 // window loses focus since one of the windows associated with the token in not focusable
4061 mWindow->consumeFocusEvent(false);
4062
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004063 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4064 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004065 mWindow->assertNoEvents();
4066}
4067
4068// A focused & mirrored window remains focused until the window and its mirror both become
4069// invisible.
4070TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
4071 setFocusedWindow(mMirror);
4072
4073 // window gets focused
4074 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4076 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004077 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004078 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4079 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004080 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4081
4082 mMirror->setVisible(false);
4083 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4084
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4086 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004087 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4089 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004090 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4091
4092 mWindow->setVisible(false);
4093 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4094
4095 // window loses focus only after all windows associated with the token become invisible.
4096 mWindow->consumeFocusEvent(false);
4097
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004098 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4099 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004100 mWindow->assertNoEvents();
4101}
4102
4103// A focused & mirrored window remains focused until both windows are removed.
4104TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
4105 setFocusedWindow(mMirror);
4106
4107 // window gets focused
4108 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4110 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004111 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004112 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4113 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004114 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4115
4116 // single window is removed but the window token remains focused
4117 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
4118
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004119 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4120 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004121 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4123 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004124 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4125
4126 // Both windows are removed
4127 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
4128 mWindow->consumeFocusEvent(false);
4129
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004130 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4131 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004132 mWindow->assertNoEvents();
4133}
4134
4135// Focus request can be pending until one window becomes visible.
4136TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
4137 // Request focus on an invisible mirror.
4138 mWindow->setVisible(false);
4139 mMirror->setVisible(false);
4140 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4141 setFocusedWindow(mMirror);
4142
4143 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004144 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07004145 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004146 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07004147
4148 mMirror->setVisible(true);
4149 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4150
4151 // window gets focused
4152 mWindow->consumeFocusEvent(true);
4153 // window gets the pending key event
4154 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4155}
Prabir Pradhan99987712020-11-10 18:43:05 -08004156
4157class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
4158protected:
4159 std::shared_ptr<FakeApplicationHandle> mApp;
4160 sp<FakeWindowHandle> mWindow;
4161 sp<FakeWindowHandle> mSecondWindow;
4162
4163 void SetUp() override {
4164 InputDispatcherTest::SetUp();
4165 mApp = std::make_shared<FakeApplicationHandle>();
4166 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
4167 mWindow->setFocusable(true);
4168 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
4169 mSecondWindow->setFocusable(true);
4170
4171 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
4172 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
4173
4174 setFocusedWindow(mWindow);
4175 mWindow->consumeFocusEvent(true);
4176 }
4177
4178 void notifyPointerCaptureChanged(bool enabled) {
4179 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(enabled);
4180 mDispatcher->notifyPointerCaptureChanged(&args);
4181 }
4182
4183 void requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window, bool enabled) {
4184 mDispatcher->requestPointerCapture(window->getToken(), enabled);
4185 mFakePolicy->waitForSetPointerCapture(enabled);
4186 notifyPointerCaptureChanged(enabled);
4187 window->consumeCaptureEvent(enabled);
4188 }
4189};
4190
4191TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
4192 // Ensure that capture cannot be obtained for unfocused windows.
4193 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
4194 mFakePolicy->assertSetPointerCaptureNotCalled();
4195 mSecondWindow->assertNoEvents();
4196
4197 // Ensure that capture can be enabled from the focus window.
4198 requestAndVerifyPointerCapture(mWindow, true);
4199
4200 // Ensure that capture cannot be disabled from a window that does not have capture.
4201 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
4202 mFakePolicy->assertSetPointerCaptureNotCalled();
4203
4204 // Ensure that capture can be disabled from the window with capture.
4205 requestAndVerifyPointerCapture(mWindow, false);
4206}
4207
4208TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
4209 requestAndVerifyPointerCapture(mWindow, true);
4210
4211 setFocusedWindow(mSecondWindow);
4212
4213 // Ensure that the capture disabled event was sent first.
4214 mWindow->consumeCaptureEvent(false);
4215 mWindow->consumeFocusEvent(false);
4216 mSecondWindow->consumeFocusEvent(true);
4217 mFakePolicy->waitForSetPointerCapture(false);
4218
4219 // Ensure that additional state changes from InputReader are not sent to the window.
4220 notifyPointerCaptureChanged(false);
4221 notifyPointerCaptureChanged(true);
4222 notifyPointerCaptureChanged(false);
4223 mWindow->assertNoEvents();
4224 mSecondWindow->assertNoEvents();
4225 mFakePolicy->assertSetPointerCaptureNotCalled();
4226}
4227
4228TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
4229 requestAndVerifyPointerCapture(mWindow, true);
4230
4231 // InputReader unexpectedly disables and enables pointer capture.
4232 notifyPointerCaptureChanged(false);
4233 notifyPointerCaptureChanged(true);
4234
4235 // Ensure that Pointer Capture is disabled.
Prabir Pradhan7d030382020-12-21 07:58:35 -08004236 mFakePolicy->waitForSetPointerCapture(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08004237 mWindow->consumeCaptureEvent(false);
4238 mWindow->assertNoEvents();
4239}
4240
Prabir Pradhan167e6d92021-02-04 16:18:17 -08004241TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
4242 requestAndVerifyPointerCapture(mWindow, true);
4243
4244 // The first window loses focus.
4245 setFocusedWindow(mSecondWindow);
4246 mFakePolicy->waitForSetPointerCapture(false);
4247 mWindow->consumeCaptureEvent(false);
4248
4249 // Request Pointer Capture from the second window before the notification from InputReader
4250 // arrives.
4251 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
4252 mFakePolicy->waitForSetPointerCapture(true);
4253
4254 // InputReader notifies Pointer Capture was disabled (because of the focus change).
4255 notifyPointerCaptureChanged(false);
4256
4257 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
4258 notifyPointerCaptureChanged(true);
4259
4260 mSecondWindow->consumeFocusEvent(true);
4261 mSecondWindow->consumeCaptureEvent(true);
4262}
4263
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004264class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
4265protected:
4266 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino6d52e542021-02-15 18:38:10 +00004267 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004268 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004269 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004270
4271 sp<FakeWindowHandle> mTouchWindow;
4272
4273 virtual void SetUp() override {
4274 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00004275 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004276 mDispatcher->setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode::BLOCK);
4277 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
4278 }
4279
4280 virtual void TearDown() override {
4281 InputDispatcherTest::TearDown();
4282 mTouchWindow.clear();
4283 }
4284
4285 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name,
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004286 os::TouchOcclusionMode mode, float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004287 sp<FakeWindowHandle> window = getWindow(uid, name);
4288 window->setFlags(InputWindowInfo::Flag::NOT_TOUCHABLE);
4289 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004290 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004291 return window;
4292 }
4293
4294 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
4295 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
4296 sp<FakeWindowHandle> window =
4297 new FakeWindowHandle(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
4298 // Generate an arbitrary PID based on the UID
4299 window->setOwnerInfo(1777 + (uid % 10000), uid);
4300 return window;
4301 }
4302
4303 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
4304 NotifyMotionArgs args =
4305 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4306 ADISPLAY_ID_DEFAULT, points);
4307 mDispatcher->notifyMotion(&args);
4308 }
4309};
4310
4311TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004312 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004313 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004314 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004315
4316 touch();
4317
4318 mTouchWindow->assertNoEvents();
4319}
4320
4321TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004322 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
4323 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004324
4325 touch();
4326
4327 mTouchWindow->consumeAnyMotionDown();
4328}
4329
4330TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004331 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004332 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004333 w->setFrame(Rect(0, 0, 50, 50));
4334 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004335
4336 touch({PointF{100, 100}});
4337
4338 mTouchWindow->consumeAnyMotionDown();
4339}
4340
4341TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004342 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00004343 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004344 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4345
4346 touch();
4347
4348 mTouchWindow->consumeAnyMotionDown();
4349}
4350
4351TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
4352 const sp<FakeWindowHandle>& w =
4353 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
4354 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004355
4356 touch();
4357
4358 mTouchWindow->consumeAnyMotionDown();
4359}
4360
4361TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004362 const sp<FakeWindowHandle>& w =
4363 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.7f);
4364 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4365
4366 touch();
4367
4368 mTouchWindow->consumeAnyMotionDown();
4369}
4370
4371TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
4372 const sp<FakeWindowHandle>& w =
4373 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
4374 MAXIMUM_OBSCURING_OPACITY);
4375 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004376
4377 touch();
4378
4379 mTouchWindow->consumeAnyMotionDown();
4380}
4381
4382TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004383 const sp<FakeWindowHandle>& w =
4384 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.9f);
4385 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4386
4387 touch();
4388
4389 mTouchWindow->assertNoEvents();
4390}
4391
4392TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
4393 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
4394 const sp<FakeWindowHandle>& w1 =
4395 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY, 0.7f);
4396 const sp<FakeWindowHandle>& w2 =
4397 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY, 0.7f);
4398 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
4399
4400 touch();
4401
4402 mTouchWindow->assertNoEvents();
4403}
4404
4405TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
4406 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
4407 const sp<FakeWindowHandle>& w1 =
4408 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY, 0.5f);
4409 const sp<FakeWindowHandle>& w2 =
4410 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY, 0.5f);
4411 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
4412
4413 touch();
4414
4415 mTouchWindow->consumeAnyMotionDown();
4416}
4417
4418TEST_F(InputDispatcherUntrustedTouchesTest,
4419 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
4420 const sp<FakeWindowHandle>& wB =
4421 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.7f);
4422 const sp<FakeWindowHandle>& wC =
4423 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY, 0.7f);
4424 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
4425
4426 touch();
4427
4428 mTouchWindow->consumeAnyMotionDown();
4429}
4430
4431TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
4432 const sp<FakeWindowHandle>& wB =
4433 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.7f);
4434 const sp<FakeWindowHandle>& wC =
4435 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY, 0.9f);
4436 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004437
4438 touch();
4439
4440 mTouchWindow->assertNoEvents();
4441}
4442
Bernardo Rufino6d52e542021-02-15 18:38:10 +00004443TEST_F(InputDispatcherUntrustedTouchesTest,
4444 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
4445 const sp<FakeWindowHandle>& wA =
4446 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY, 0.7f);
4447 const sp<FakeWindowHandle>& wB =
4448 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.9f);
4449 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
4450
4451 touch();
4452
4453 mTouchWindow->assertNoEvents();
4454}
4455
4456TEST_F(InputDispatcherUntrustedTouchesTest,
4457 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
4458 const sp<FakeWindowHandle>& wA =
4459 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY, 0.9f);
4460 const sp<FakeWindowHandle>& wB =
4461 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.7f);
4462 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
4463
4464 touch();
4465
4466 mTouchWindow->consumeAnyMotionDown();
4467}
4468
4469TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
4470 const sp<FakeWindowHandle>& w =
4471 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY, 0.9f);
4472 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4473
4474 touch();
4475
4476 mTouchWindow->consumeAnyMotionDown();
4477}
4478
4479TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
4480 const sp<FakeWindowHandle>& w =
4481 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
4482 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4483
4484 touch();
4485
4486 mTouchWindow->consumeAnyMotionDown();
4487}
4488
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00004489TEST_F(InputDispatcherUntrustedTouchesTest,
4490 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
4491 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
4492 const sp<FakeWindowHandle>& w =
4493 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
4494 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4495
4496 touch();
4497
4498 mTouchWindow->assertNoEvents();
4499}
4500
4501TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
4502 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
4503 const sp<FakeWindowHandle>& w =
4504 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
4505 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4506
4507 touch();
4508
4509 mTouchWindow->consumeAnyMotionDown();
4510}
4511
4512TEST_F(InputDispatcherUntrustedTouchesTest,
4513 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
4514 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
4515 const sp<FakeWindowHandle>& w =
4516 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.9f);
4517 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4518
4519 touch();
4520
4521 mTouchWindow->consumeAnyMotionDown();
4522}
4523
Garfield Tane84e6f92019-08-29 17:28:41 -07004524} // namespace android::inputdispatcher