blob: 5cdcfaf38e013abcfc142f6326ac3bca8b04b391 [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
Bernardo Rufino7393d172021-02-26 13:56:11 +0000901 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
902
chaviwd1c23182019-12-20 18:44:56 -0800903 void setFrame(const Rect& frame) {
904 mInfo.frameLeft = frame.left;
905 mInfo.frameTop = frame.top;
906 mInfo.frameRight = frame.right;
907 mInfo.frameBottom = frame.bottom;
chaviw1ff3d1e2020-07-01 15:53:47 -0700908 mInfo.transform.set(frame.left, frame.top);
chaviwd1c23182019-12-20 18:44:56 -0800909 mInfo.touchableRegion.clear();
910 mInfo.addTouchableRegion(frame);
911 }
912
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +0000913 void addFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags |= flags; }
914
Michael Wright44753b12020-07-08 13:48:11 +0100915 void setFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags = flags; }
chaviwd1c23182019-12-20 18:44:56 -0800916
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500917 void setInputFeatures(InputWindowInfo::Feature features) { mInfo.inputFeatures = features; }
918
chaviw9eaa22c2020-07-01 16:21:27 -0700919 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
920 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
921 }
922
923 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -0700924
yunho.shinf4a80b82020-11-16 21:13:57 +0900925 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
926
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800927 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
928 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
929 expectedFlags);
930 }
931
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700932 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
933 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
934 }
935
Svet Ganov5d3bc372020-01-26 23:11:07 -0800936 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000937 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800938 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
939 expectedFlags);
940 }
941
942 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000943 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800944 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
945 expectedFlags);
946 }
947
948 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000949 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000950 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
951 }
952
953 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
954 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800955 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
956 expectedFlags);
957 }
958
Svet Ganov5d3bc372020-01-26 23:11:07 -0800959 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000960 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
961 int32_t expectedFlags = 0) {
962 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
963 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -0800964 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
965 }
966
967 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000968 int32_t expectedFlags = 0) {
969 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
970 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -0800971 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
972 }
973
974 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000975 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000976 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
977 expectedFlags);
978 }
979
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500980 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
981 int32_t expectedFlags = 0) {
982 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
983 expectedFlags);
984 }
985
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100986 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
987 ASSERT_NE(mInputReceiver, nullptr)
988 << "Cannot consume events from a window with no receiver";
989 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
990 }
991
Prabir Pradhan99987712020-11-10 18:43:05 -0800992 void consumeCaptureEvent(bool hasCapture) {
993 ASSERT_NE(mInputReceiver, nullptr)
994 << "Cannot consume events from a window with no receiver";
995 mInputReceiver->consumeCaptureEvent(hasCapture);
996 }
997
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000998 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
999 std::optional<int32_t> expectedDisplayId,
1000 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001001 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1002 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1003 expectedFlags);
1004 }
1005
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001006 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001007 if (mInputReceiver == nullptr) {
1008 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1009 return std::nullopt;
1010 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001011 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001012 }
1013
1014 void finishEvent(uint32_t sequenceNum) {
1015 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1016 mInputReceiver->finishEvent(sequenceNum);
1017 }
1018
chaviwaf87b3e2019-10-01 16:59:28 -07001019 InputEvent* consume() {
1020 if (mInputReceiver == nullptr) {
1021 return nullptr;
1022 }
1023 return mInputReceiver->consume();
1024 }
1025
Arthur Hungb92218b2018-08-14 12:00:21 +08001026 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001027 if (mInputReceiver == nullptr &&
1028 mInfo.inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL)) {
1029 return; // Can't receive events if the window does not have input channel
1030 }
1031 ASSERT_NE(nullptr, mInputReceiver)
1032 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001033 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001034 }
1035
chaviwaf87b3e2019-10-01 16:59:28 -07001036 sp<IBinder> getToken() { return mInfo.token; }
1037
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001038 const std::string& getName() { return mName; }
1039
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001040 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1041 mInfo.ownerPid = ownerPid;
1042 mInfo.ownerUid = ownerUid;
1043 }
1044
chaviwd1c23182019-12-20 18:44:56 -08001045private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001046 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001047 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001048 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001049};
1050
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001051std::atomic<int32_t> FakeWindowHandle::sId{1};
1052
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001053static InputEventInjectionResult injectKey(
1054 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
1055 int32_t displayId = ADISPLAY_ID_NONE,
1056 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1057 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001058 KeyEvent event;
1059 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1060
1061 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001062 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001063 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
1064 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001065
1066 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001067 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
1068 injectionTimeout,
1069 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
Arthur Hungb92218b2018-08-14 12:00:21 +08001070}
1071
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001072static InputEventInjectionResult injectKeyDown(const sp<InputDispatcher>& dispatcher,
1073 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001074 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
1075}
1076
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001077static InputEventInjectionResult injectKeyUp(const sp<InputDispatcher>& dispatcher,
1078 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001079 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
1080}
1081
Garfield Tandf26e862020-07-01 20:18:19 -07001082class PointerBuilder {
1083public:
1084 PointerBuilder(int32_t id, int32_t toolType) {
1085 mProperties.clear();
1086 mProperties.id = id;
1087 mProperties.toolType = toolType;
1088 mCoords.clear();
1089 }
1090
1091 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1092
1093 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1094
1095 PointerBuilder& axis(int32_t axis, float value) {
1096 mCoords.setAxisValue(axis, value);
1097 return *this;
1098 }
1099
1100 PointerProperties buildProperties() const { return mProperties; }
1101
1102 PointerCoords buildCoords() const { return mCoords; }
1103
1104private:
1105 PointerProperties mProperties;
1106 PointerCoords mCoords;
1107};
1108
1109class MotionEventBuilder {
1110public:
1111 MotionEventBuilder(int32_t action, int32_t source) {
1112 mAction = action;
1113 mSource = source;
1114 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1115 }
1116
1117 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1118 mEventTime = eventTime;
1119 return *this;
1120 }
1121
1122 MotionEventBuilder& displayId(int32_t displayId) {
1123 mDisplayId = displayId;
1124 return *this;
1125 }
1126
1127 MotionEventBuilder& actionButton(int32_t actionButton) {
1128 mActionButton = actionButton;
1129 return *this;
1130 }
1131
1132 MotionEventBuilder& buttonState(int32_t actionButton) {
1133 mActionButton = actionButton;
1134 return *this;
1135 }
1136
1137 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1138 mRawXCursorPosition = rawXCursorPosition;
1139 return *this;
1140 }
1141
1142 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1143 mRawYCursorPosition = rawYCursorPosition;
1144 return *this;
1145 }
1146
1147 MotionEventBuilder& pointer(PointerBuilder pointer) {
1148 mPointers.push_back(pointer);
1149 return *this;
1150 }
1151
1152 MotionEvent build() {
1153 std::vector<PointerProperties> pointerProperties;
1154 std::vector<PointerCoords> pointerCoords;
1155 for (const PointerBuilder& pointer : mPointers) {
1156 pointerProperties.push_back(pointer.buildProperties());
1157 pointerCoords.push_back(pointer.buildCoords());
1158 }
1159
1160 // Set mouse cursor position for the most common cases to avoid boilerplate.
1161 if (mSource == AINPUT_SOURCE_MOUSE &&
1162 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1163 mPointers.size() == 1) {
1164 mRawXCursorPosition = pointerCoords[0].getX();
1165 mRawYCursorPosition = pointerCoords[0].getY();
1166 }
1167
1168 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001169 ui::Transform identityTransform;
Garfield Tandf26e862020-07-01 20:18:19 -07001170 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
1171 mAction, mActionButton, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001172 mButtonState, MotionClassification::NONE, identityTransform,
1173 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
1174 mRawYCursorPosition, mEventTime, mEventTime, mPointers.size(),
1175 pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001176
1177 return event;
1178 }
1179
1180private:
1181 int32_t mAction;
1182 int32_t mSource;
1183 nsecs_t mEventTime;
1184 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1185 int32_t mActionButton{0};
1186 int32_t mButtonState{0};
1187 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1188 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1189
1190 std::vector<PointerBuilder> mPointers;
1191};
1192
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001193static InputEventInjectionResult injectMotionEvent(
Garfield Tandf26e862020-07-01 20:18:19 -07001194 const sp<InputDispatcher>& dispatcher, const MotionEvent& event,
1195 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001196 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT) {
Garfield Tandf26e862020-07-01 20:18:19 -07001197 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
1198 injectionTimeout,
1199 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
1200}
1201
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001202static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001203 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
1204 const PointF& position,
1205 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001206 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1207 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001208 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001209 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Garfield Tandf26e862020-07-01 20:18:19 -07001210 MotionEvent event = MotionEventBuilder(action, source)
1211 .displayId(displayId)
1212 .eventTime(eventTime)
1213 .rawXCursorPosition(cursorPosition.x)
1214 .rawYCursorPosition(cursorPosition.y)
1215 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1216 .x(position.x)
1217 .y(position.y))
1218 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001219
1220 // Inject event until dispatch out.
Garfield Tandf26e862020-07-01 20:18:19 -07001221 return injectMotionEvent(dispatcher, event);
Arthur Hungb92218b2018-08-14 12:00:21 +08001222}
1223
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001224static InputEventInjectionResult injectMotionDown(const sp<InputDispatcher>& dispatcher,
1225 int32_t source, int32_t displayId,
1226 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001227 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001228}
1229
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001230static InputEventInjectionResult injectMotionUp(const sp<InputDispatcher>& dispatcher,
1231 int32_t source, int32_t displayId,
1232 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001233 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001234}
1235
Jackal Guof9696682018-10-05 12:23:23 +08001236static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1237 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1238 // Define a valid key event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001239 NotifyKeyArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1240 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1241 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001242
1243 return args;
1244}
1245
chaviwd1c23182019-12-20 18:44:56 -08001246static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1247 const std::vector<PointF>& points) {
1248 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001249 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1250 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1251 }
1252
chaviwd1c23182019-12-20 18:44:56 -08001253 PointerProperties pointerProperties[pointerCount];
1254 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001255
chaviwd1c23182019-12-20 18:44:56 -08001256 for (size_t i = 0; i < pointerCount; i++) {
1257 pointerProperties[i].clear();
1258 pointerProperties[i].id = i;
1259 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001260
chaviwd1c23182019-12-20 18:44:56 -08001261 pointerCoords[i].clear();
1262 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1263 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1264 }
Jackal Guof9696682018-10-05 12:23:23 +08001265
1266 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1267 // Define a valid motion event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001268 NotifyMotionArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001269 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1270 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001271 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1272 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001273 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1274 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001275
1276 return args;
1277}
1278
chaviwd1c23182019-12-20 18:44:56 -08001279static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1280 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1281}
1282
Prabir Pradhan99987712020-11-10 18:43:05 -08001283static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(bool enabled) {
1284 return NotifyPointerCaptureChangedArgs(/* id */ 0, systemTime(SYSTEM_TIME_MONOTONIC), enabled);
1285}
1286
Arthur Hungb92218b2018-08-14 12:00:21 +08001287TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001288 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001289 sp<FakeWindowHandle> window =
1290 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001291
Arthur Hung72d8dc32020-03-28 00:48:39 +00001292 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1294 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1295 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001296
1297 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001298 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001299}
1300
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001301/**
1302 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1303 * To ensure that window receives only events that were directly inside of it, add
1304 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1305 * when finding touched windows.
1306 * This test serves as a sanity check for the next test, where setInputWindows is
1307 * called twice.
1308 */
1309TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001310 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001311 sp<FakeWindowHandle> window =
1312 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1313 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001314 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001315
1316 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001318 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1319 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001320 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001321
1322 // Window should receive motion event.
1323 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1324}
1325
1326/**
1327 * Calling setInputWindows twice, with the same info, should not cause any issues.
1328 * To ensure that window receives only events that were directly inside of it, add
1329 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1330 * when finding touched windows.
1331 */
1332TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001333 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001334 sp<FakeWindowHandle> window =
1335 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1336 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001337 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001338
1339 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1340 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001341 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001342 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1343 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001344 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001345
1346 // Window should receive motion event.
1347 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1348}
1349
Arthur Hungb92218b2018-08-14 12:00:21 +08001350// The foreground window should receive the first touch down event.
1351TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001352 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001353 sp<FakeWindowHandle> windowTop =
1354 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1355 sp<FakeWindowHandle> windowSecond =
1356 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001357
Arthur Hung72d8dc32020-03-28 00:48:39 +00001358 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1360 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1361 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001362
1363 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001364 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001365 windowSecond->assertNoEvents();
1366}
1367
Garfield Tandf26e862020-07-01 20:18:19 -07001368TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001369 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001370 sp<FakeWindowHandle> windowLeft =
1371 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1372 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001373 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001374 sp<FakeWindowHandle> windowRight =
1375 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1376 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001377 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001378
1379 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1380
1381 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
1382
1383 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001385 injectMotionEvent(mDispatcher,
1386 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1387 AINPUT_SOURCE_MOUSE)
1388 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1389 .x(900)
1390 .y(400))
1391 .build()));
1392 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1393 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1394 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1395 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1396
1397 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001398 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001399 injectMotionEvent(mDispatcher,
1400 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1401 AINPUT_SOURCE_MOUSE)
1402 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1403 .x(300)
1404 .y(400))
1405 .build()));
1406 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1407 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1408 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1409 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1410 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1411 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1412
1413 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001415 injectMotionEvent(mDispatcher,
1416 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1417 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1418 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1419 .x(300)
1420 .y(400))
1421 .build()));
1422 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1423
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001425 injectMotionEvent(mDispatcher,
1426 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1427 AINPUT_SOURCE_MOUSE)
1428 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1429 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1430 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1431 .x(300)
1432 .y(400))
1433 .build()));
1434 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1435 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1436
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001437 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001438 injectMotionEvent(mDispatcher,
1439 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1440 AINPUT_SOURCE_MOUSE)
1441 .buttonState(0)
1442 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1443 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1444 .x(300)
1445 .y(400))
1446 .build()));
1447 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1448 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1449
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001451 injectMotionEvent(mDispatcher,
1452 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1453 .buttonState(0)
1454 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1455 .x(300)
1456 .y(400))
1457 .build()));
1458 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1459
1460 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001461 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001462 injectMotionEvent(mDispatcher,
1463 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1464 AINPUT_SOURCE_MOUSE)
1465 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1466 .x(900)
1467 .y(400))
1468 .build()));
1469 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1470 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1471 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1472 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1473 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1474 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1475}
1476
1477// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
1478// directly in this test.
1479TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001480 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001481 sp<FakeWindowHandle> window =
1482 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1483 window->setFrame(Rect(0, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001484 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001485
1486 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1487
1488 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1489
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001490 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001491 injectMotionEvent(mDispatcher,
1492 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
1493 AINPUT_SOURCE_MOUSE)
1494 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1495 .x(300)
1496 .y(400))
1497 .build()));
1498 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1499 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1500
1501 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001502 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001503 injectMotionEvent(mDispatcher,
1504 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1505 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1506 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1507 .x(300)
1508 .y(400))
1509 .build()));
1510 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1511
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001512 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001513 injectMotionEvent(mDispatcher,
1514 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1515 AINPUT_SOURCE_MOUSE)
1516 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1517 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1518 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1519 .x(300)
1520 .y(400))
1521 .build()));
1522 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1523 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1524
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001525 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001526 injectMotionEvent(mDispatcher,
1527 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1528 AINPUT_SOURCE_MOUSE)
1529 .buttonState(0)
1530 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1531 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1532 .x(300)
1533 .y(400))
1534 .build()));
1535 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1536 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1537
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001538 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001539 injectMotionEvent(mDispatcher,
1540 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1541 .buttonState(0)
1542 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1543 .x(300)
1544 .y(400))
1545 .build()));
1546 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1547
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001548 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001549 injectMotionEvent(mDispatcher,
1550 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
1551 AINPUT_SOURCE_MOUSE)
1552 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1553 .x(300)
1554 .y(400))
1555 .build()));
1556 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1557 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1558}
1559
Garfield Tan00f511d2019-06-12 16:55:40 -07001560TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07001561 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07001562
1563 sp<FakeWindowHandle> windowLeft =
1564 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1565 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001566 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001567 sp<FakeWindowHandle> windowRight =
1568 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1569 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001570 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001571
1572 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1573
Arthur Hung72d8dc32020-03-28 00:48:39 +00001574 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001575
1576 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1577 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001578 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07001579 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001580 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001581 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001582 windowRight->assertNoEvents();
1583}
1584
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001585TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001586 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001587 sp<FakeWindowHandle> window =
1588 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07001589 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001590
Arthur Hung72d8dc32020-03-28 00:48:39 +00001591 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001592 setFocusedWindow(window);
1593
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001594 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001595
1596 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1597 mDispatcher->notifyKey(&keyArgs);
1598
1599 // Window should receive key down event.
1600 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1601
1602 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1603 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001604 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001605 mDispatcher->notifyDeviceReset(&args);
1606 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1607 AKEY_EVENT_FLAG_CANCELED);
1608}
1609
1610TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001611 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001612 sp<FakeWindowHandle> window =
1613 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1614
Arthur Hung72d8dc32020-03-28 00:48:39 +00001615 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001616
1617 NotifyMotionArgs motionArgs =
1618 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1619 ADISPLAY_ID_DEFAULT);
1620 mDispatcher->notifyMotion(&motionArgs);
1621
1622 // Window should receive motion down event.
1623 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1624
1625 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1626 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001627 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001628 mDispatcher->notifyDeviceReset(&args);
1629 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1630 0 /*expectedFlags*/);
1631}
1632
Svet Ganov5d3bc372020-01-26 23:11:07 -08001633TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07001634 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001635
1636 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001637 sp<FakeWindowHandle> firstWindow =
1638 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1639 sp<FakeWindowHandle> secondWindow =
1640 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001641
1642 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001643 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001644
1645 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001646 NotifyMotionArgs downMotionArgs =
1647 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1648 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001649 mDispatcher->notifyMotion(&downMotionArgs);
1650 // Only the first window should get the down event
1651 firstWindow->consumeMotionDown();
1652 secondWindow->assertNoEvents();
1653
1654 // Transfer touch focus to the second window
1655 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1656 // The first window gets cancel and the second gets down
1657 firstWindow->consumeMotionCancel();
1658 secondWindow->consumeMotionDown();
1659
1660 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001661 NotifyMotionArgs upMotionArgs =
1662 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1663 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001664 mDispatcher->notifyMotion(&upMotionArgs);
1665 // The first window gets no events and the second gets up
1666 firstWindow->assertNoEvents();
1667 secondWindow->consumeMotionUp();
1668}
1669
1670TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001671 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001672
1673 PointF touchPoint = {10, 10};
1674
1675 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001676 sp<FakeWindowHandle> firstWindow =
1677 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1678 sp<FakeWindowHandle> secondWindow =
1679 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001680
1681 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001682 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001683
1684 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001685 NotifyMotionArgs downMotionArgs =
1686 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1687 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001688 mDispatcher->notifyMotion(&downMotionArgs);
1689 // Only the first window should get the down event
1690 firstWindow->consumeMotionDown();
1691 secondWindow->assertNoEvents();
1692
1693 // Send pointer down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001694 NotifyMotionArgs pointerDownMotionArgs =
1695 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
1696 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1697 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1698 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001699 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1700 // Only the first window should get the pointer down event
1701 firstWindow->consumeMotionPointerDown(1);
1702 secondWindow->assertNoEvents();
1703
1704 // Transfer touch focus to the second window
1705 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1706 // The first window gets cancel and the second gets down and pointer down
1707 firstWindow->consumeMotionCancel();
1708 secondWindow->consumeMotionDown();
1709 secondWindow->consumeMotionPointerDown(1);
1710
1711 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001712 NotifyMotionArgs pointerUpMotionArgs =
1713 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
1714 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1715 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1716 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001717 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1718 // The first window gets nothing and the second gets pointer up
1719 firstWindow->assertNoEvents();
1720 secondWindow->consumeMotionPointerUp(1);
1721
1722 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001723 NotifyMotionArgs upMotionArgs =
1724 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1725 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001726 mDispatcher->notifyMotion(&upMotionArgs);
1727 // The first window gets nothing and the second gets up
1728 firstWindow->assertNoEvents();
1729 secondWindow->consumeMotionUp();
1730}
1731
1732TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001733 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001734
1735 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001736 sp<FakeWindowHandle> firstWindow =
1737 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001738 firstWindow->setFrame(Rect(0, 0, 600, 400));
Michael Wright44753b12020-07-08 13:48:11 +01001739 firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1740 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001741
1742 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001743 sp<FakeWindowHandle> secondWindow =
1744 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001745 secondWindow->setFrame(Rect(0, 400, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001746 secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1747 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001748
1749 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001750 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001751
1752 PointF pointInFirst = {300, 200};
1753 PointF pointInSecond = {300, 600};
1754
1755 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001756 NotifyMotionArgs firstDownMotionArgs =
1757 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1758 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001759 mDispatcher->notifyMotion(&firstDownMotionArgs);
1760 // Only the first window should get the down event
1761 firstWindow->consumeMotionDown();
1762 secondWindow->assertNoEvents();
1763
1764 // Send down to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001765 NotifyMotionArgs secondDownMotionArgs =
1766 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
1767 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1768 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1769 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001770 mDispatcher->notifyMotion(&secondDownMotionArgs);
1771 // The first window gets a move and the second a down
1772 firstWindow->consumeMotionMove();
1773 secondWindow->consumeMotionDown();
1774
1775 // Transfer touch focus to the second window
1776 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1777 // The first window gets cancel and the new gets pointer down (it already saw down)
1778 firstWindow->consumeMotionCancel();
1779 secondWindow->consumeMotionPointerDown(1);
1780
1781 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001782 NotifyMotionArgs pointerUpMotionArgs =
1783 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
1784 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1785 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1786 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001787 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1788 // The first window gets nothing and the second gets pointer up
1789 firstWindow->assertNoEvents();
1790 secondWindow->consumeMotionPointerUp(1);
1791
1792 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001793 NotifyMotionArgs upMotionArgs =
1794 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1795 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001796 mDispatcher->notifyMotion(&upMotionArgs);
1797 // The first window gets nothing and the second gets up
1798 firstWindow->assertNoEvents();
1799 secondWindow->consumeMotionUp();
1800}
1801
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001802TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001803 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001804 sp<FakeWindowHandle> window =
1805 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1806
Vishnu Nair47074b82020-08-14 11:54:47 -07001807 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001808 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001809 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001810
1811 window->consumeFocusEvent(true);
1812
1813 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1814 mDispatcher->notifyKey(&keyArgs);
1815
1816 // Window should receive key down event.
1817 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1818}
1819
1820TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001821 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001822 sp<FakeWindowHandle> window =
1823 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1824
Arthur Hung72d8dc32020-03-28 00:48:39 +00001825 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001826
1827 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1828 mDispatcher->notifyKey(&keyArgs);
1829 mDispatcher->waitForIdle();
1830
1831 window->assertNoEvents();
1832}
1833
1834// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1835TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07001836 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001837 sp<FakeWindowHandle> window =
1838 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1839
Arthur Hung72d8dc32020-03-28 00:48:39 +00001840 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001841
1842 // Send key
1843 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1844 mDispatcher->notifyKey(&keyArgs);
1845 // Send motion
1846 NotifyMotionArgs motionArgs =
1847 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1848 ADISPLAY_ID_DEFAULT);
1849 mDispatcher->notifyMotion(&motionArgs);
1850
1851 // Window should receive only the motion event
1852 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1853 window->assertNoEvents(); // Key event or focus event will not be received
1854}
1855
arthurhungea3f4fc2020-12-21 23:18:53 +08001856TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
1857 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1858
1859 // Create first non touch modal window that supports split touch
1860 sp<FakeWindowHandle> firstWindow =
1861 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1862 firstWindow->setFrame(Rect(0, 0, 600, 400));
1863 firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1864 InputWindowInfo::Flag::SPLIT_TOUCH);
1865
1866 // Create second non touch modal window that supports split touch
1867 sp<FakeWindowHandle> secondWindow =
1868 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
1869 secondWindow->setFrame(Rect(0, 400, 600, 800));
1870 secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1871 InputWindowInfo::Flag::SPLIT_TOUCH);
1872
1873 // Add the windows to the dispatcher
1874 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
1875
1876 PointF pointInFirst = {300, 200};
1877 PointF pointInSecond = {300, 600};
1878
1879 // Send down to the first window
1880 NotifyMotionArgs firstDownMotionArgs =
1881 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1882 ADISPLAY_ID_DEFAULT, {pointInFirst});
1883 mDispatcher->notifyMotion(&firstDownMotionArgs);
1884 // Only the first window should get the down event
1885 firstWindow->consumeMotionDown();
1886 secondWindow->assertNoEvents();
1887
1888 // Send down to the second window
1889 NotifyMotionArgs secondDownMotionArgs =
1890 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
1891 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1892 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1893 {pointInFirst, pointInSecond});
1894 mDispatcher->notifyMotion(&secondDownMotionArgs);
1895 // The first window gets a move and the second a down
1896 firstWindow->consumeMotionMove();
1897 secondWindow->consumeMotionDown();
1898
1899 // Send pointer cancel to the second window
1900 NotifyMotionArgs pointerUpMotionArgs =
1901 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
1902 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1903 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1904 {pointInFirst, pointInSecond});
1905 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
1906 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1907 // The first window gets move and the second gets cancel.
1908 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
1909 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
1910
1911 // Send up event.
1912 NotifyMotionArgs upMotionArgs =
1913 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1914 ADISPLAY_ID_DEFAULT);
1915 mDispatcher->notifyMotion(&upMotionArgs);
1916 // The first window gets up and the second gets nothing.
1917 firstWindow->consumeMotionUp();
1918 secondWindow->assertNoEvents();
1919}
1920
chaviwd1c23182019-12-20 18:44:56 -08001921class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001922public:
1923 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001924 int32_t displayId, bool isGestureMonitor = false) {
Garfield Tan15601662020-09-22 15:32:38 -07001925 base::Result<std::unique_ptr<InputChannel>> channel =
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +00001926 dispatcher->createInputMonitor(displayId, isGestureMonitor, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07001927 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00001928 }
1929
chaviwd1c23182019-12-20 18:44:56 -08001930 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1931
1932 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1933 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1934 expectedDisplayId, expectedFlags);
1935 }
1936
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001937 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
1938
1939 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1940
chaviwd1c23182019-12-20 18:44:56 -08001941 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1942 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1943 expectedDisplayId, expectedFlags);
1944 }
1945
1946 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1947 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1948 expectedDisplayId, expectedFlags);
1949 }
1950
1951 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1952
1953private:
1954 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001955};
1956
1957// Tests for gesture monitors
1958TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07001959 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001960 sp<FakeWindowHandle> window =
1961 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001962 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001963
chaviwd1c23182019-12-20 18:44:56 -08001964 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1965 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001966
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001967 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00001968 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001969 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00001970 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001971 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001972}
1973
1974TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07001975 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001976 sp<FakeWindowHandle> window =
1977 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1978
1979 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07001980 window->setFocusable(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001981
Arthur Hung72d8dc32020-03-28 00:48:39 +00001982 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001983 setFocusedWindow(window);
1984
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001985 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001986
chaviwd1c23182019-12-20 18:44:56 -08001987 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1988 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001989
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001990 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1991 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00001992 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001993 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001994}
1995
1996TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001997 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001998 sp<FakeWindowHandle> window =
1999 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002000 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00002001
chaviwd1c23182019-12-20 18:44:56 -08002002 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2003 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00002004
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002005 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002006 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002007 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00002008 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002009 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002010
2011 window->releaseChannel();
2012
chaviwd1c23182019-12-20 18:44:56 -08002013 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00002014
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002016 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002017 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08002018 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002019}
2020
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002021TEST_F(InputDispatcherTest, UnresponsiveGestureMonitor_GetsAnr) {
2022 FakeMonitorReceiver monitor =
2023 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2024 true /*isGestureMonitor*/);
2025
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002026 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002027 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
2028 std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
2029 ASSERT_TRUE(consumeSeq);
2030
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00002031 mFakePolicy->assertNotifyMonitorUnresponsiveWasCalled(DISPATCHING_TIMEOUT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002032 monitor.finishEvent(*consumeSeq);
2033 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00002034 mFakePolicy->assertNotifyMonitorResponsiveWasCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002035}
2036
chaviw81e2bb92019-12-18 15:03:51 -08002037TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002038 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
chaviw81e2bb92019-12-18 15:03:51 -08002039 sp<FakeWindowHandle> window =
2040 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2041
Arthur Hung72d8dc32020-03-28 00:48:39 +00002042 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08002043
2044 NotifyMotionArgs motionArgs =
2045 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2046 ADISPLAY_ID_DEFAULT);
2047
2048 mDispatcher->notifyMotion(&motionArgs);
2049 // Window should receive motion down event.
2050 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2051
2052 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002053 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08002054 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
2055 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
2056 motionArgs.pointerCoords[0].getX() - 10);
2057
2058 mDispatcher->notifyMotion(&motionArgs);
2059 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
2060 0 /*expectedFlags*/);
2061}
2062
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002063/**
2064 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
2065 * the device default right away. In the test scenario, we check both the default value,
2066 * and the action of enabling / disabling.
2067 */
2068TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07002069 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002070 sp<FakeWindowHandle> window =
2071 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2072
2073 // Set focused application.
2074 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002075 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002076
2077 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00002078 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002079 setFocusedWindow(window);
2080
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002081 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2082
2083 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07002084 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002085 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002086 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
2087
2088 SCOPED_TRACE("Disable touch mode");
2089 mDispatcher->setInTouchMode(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07002090 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002091 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002092 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002093 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
2094
2095 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07002096 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002097 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002098 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
2099
2100 SCOPED_TRACE("Enable touch mode again");
2101 mDispatcher->setInTouchMode(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07002102 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002103 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002104 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002105 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2106
2107 window->assertNoEvents();
2108}
2109
Gang Wange9087892020-01-07 12:17:14 -05002110TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002111 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Gang Wange9087892020-01-07 12:17:14 -05002112 sp<FakeWindowHandle> window =
2113 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2114
2115 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002116 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05002117
Arthur Hung72d8dc32020-03-28 00:48:39 +00002118 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002119 setFocusedWindow(window);
2120
Gang Wange9087892020-01-07 12:17:14 -05002121 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2122
2123 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2124 mDispatcher->notifyKey(&keyArgs);
2125
2126 InputEvent* event = window->consume();
2127 ASSERT_NE(event, nullptr);
2128
2129 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2130 ASSERT_NE(verified, nullptr);
2131 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
2132
2133 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
2134 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
2135 ASSERT_EQ(keyArgs.source, verified->source);
2136 ASSERT_EQ(keyArgs.displayId, verified->displayId);
2137
2138 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
2139
2140 ASSERT_EQ(keyArgs.action, verifiedKey.action);
2141 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05002142 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
2143 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
2144 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
2145 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
2146 ASSERT_EQ(0, verifiedKey.repeatCount);
2147}
2148
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002149TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002150 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002151 sp<FakeWindowHandle> window =
2152 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2153
2154 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2155
Arthur Hung72d8dc32020-03-28 00:48:39 +00002156 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002157
2158 NotifyMotionArgs motionArgs =
2159 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2160 ADISPLAY_ID_DEFAULT);
2161 mDispatcher->notifyMotion(&motionArgs);
2162
2163 InputEvent* event = window->consume();
2164 ASSERT_NE(event, nullptr);
2165
2166 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2167 ASSERT_NE(verified, nullptr);
2168 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
2169
2170 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
2171 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
2172 EXPECT_EQ(motionArgs.source, verified->source);
2173 EXPECT_EQ(motionArgs.displayId, verified->displayId);
2174
2175 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
2176
2177 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
2178 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
2179 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
2180 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
2181 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
2182 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
2183 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
2184}
2185
Prabir Pradhanbd527712021-03-09 19:17:09 -08002186TEST_F(InputDispatcherTest, NonPointerMotionEvent_NotTransformed) {
yunho.shinf4a80b82020-11-16 21:13:57 +09002187 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2188 sp<FakeWindowHandle> window =
2189 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2190 const std::string name = window->getName();
2191
2192 // Window gets transformed by offset values.
2193 window->setWindowOffset(500.0f, 500.0f);
2194
2195 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2196 window->setFocusable(true);
2197
2198 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2199
2200 // First, we set focused window so that focusedWindowHandle is not null.
2201 setFocusedWindow(window);
2202
2203 // Second, we consume focus event if it is right or wrong according to onFocusChangedLocked.
2204 window->consumeFocusEvent(true);
2205
Prabir Pradhanbd527712021-03-09 19:17:09 -08002206 constexpr const std::array nonPointerSources = {AINPUT_SOURCE_TRACKBALL,
2207 AINPUT_SOURCE_MOUSE_RELATIVE,
2208 AINPUT_SOURCE_JOYSTICK};
2209 for (const int source : nonPointerSources) {
2210 // Notify motion with a non-pointer source.
2211 NotifyMotionArgs motionArgs =
2212 generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, source, ADISPLAY_ID_DEFAULT);
2213 mDispatcher->notifyMotion(&motionArgs);
yunho.shinf4a80b82020-11-16 21:13:57 +09002214
Prabir Pradhanbd527712021-03-09 19:17:09 -08002215 InputEvent* event = window->consume();
2216 ASSERT_NE(event, nullptr);
2217 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
2218 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
2219 << " event, got " << inputEventTypeToString(event->getType()) << " event";
yunho.shinf4a80b82020-11-16 21:13:57 +09002220
Prabir Pradhanbd527712021-03-09 19:17:09 -08002221 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
2222 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, motionEvent.getAction());
2223 EXPECT_EQ(motionArgs.pointerCount, motionEvent.getPointerCount());
yunho.shinf4a80b82020-11-16 21:13:57 +09002224
Prabir Pradhanbd527712021-03-09 19:17:09 -08002225 float expectedX = motionArgs.pointerCoords[0].getX();
2226 float expectedY = motionArgs.pointerCoords[0].getY();
yunho.shinf4a80b82020-11-16 21:13:57 +09002227
Prabir Pradhanbd527712021-03-09 19:17:09 -08002228 // Ensure the axis values from the final motion event are not transformed.
2229 EXPECT_EQ(expectedX, motionEvent.getX(0))
2230 << "expected " << expectedX << " for x coord of " << name.c_str() << ", got "
2231 << motionEvent.getX(0);
2232 EXPECT_EQ(expectedY, motionEvent.getY(0))
2233 << "expected " << expectedY << " for y coord of " << name.c_str() << ", got "
2234 << motionEvent.getY(0);
2235 // Ensure the raw and transformed axis values for the motion event are the same.
2236 EXPECT_EQ(motionEvent.getRawX(0), motionEvent.getX(0))
2237 << "expected raw and transformed X-axis values to be equal";
2238 EXPECT_EQ(motionEvent.getRawY(0), motionEvent.getY(0))
2239 << "expected raw and transformed Y-axis values to be equal";
2240 }
yunho.shinf4a80b82020-11-16 21:13:57 +09002241}
2242
chaviw09c8d2d2020-08-24 15:48:26 -07002243/**
2244 * Ensure that separate calls to sign the same data are generating the same key.
2245 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
2246 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
2247 * tests.
2248 */
2249TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
2250 KeyEvent event = getTestKeyEvent();
2251 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2252
2253 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
2254 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
2255 ASSERT_EQ(hmac1, hmac2);
2256}
2257
2258/**
2259 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
2260 */
2261TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
2262 KeyEvent event = getTestKeyEvent();
2263 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2264 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
2265
2266 verifiedEvent.deviceId += 1;
2267 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2268
2269 verifiedEvent.source += 1;
2270 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2271
2272 verifiedEvent.eventTimeNanos += 1;
2273 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2274
2275 verifiedEvent.displayId += 1;
2276 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2277
2278 verifiedEvent.action += 1;
2279 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2280
2281 verifiedEvent.downTimeNanos += 1;
2282 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2283
2284 verifiedEvent.flags += 1;
2285 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2286
2287 verifiedEvent.keyCode += 1;
2288 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2289
2290 verifiedEvent.scanCode += 1;
2291 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2292
2293 verifiedEvent.metaState += 1;
2294 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2295
2296 verifiedEvent.repeatCount += 1;
2297 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2298}
2299
Vishnu Nair958da932020-08-21 17:12:37 -07002300TEST_F(InputDispatcherTest, SetFocusedWindow) {
2301 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2302 sp<FakeWindowHandle> windowTop =
2303 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2304 sp<FakeWindowHandle> windowSecond =
2305 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2306 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2307
2308 // Top window is also focusable but is not granted focus.
2309 windowTop->setFocusable(true);
2310 windowSecond->setFocusable(true);
2311 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2312 setFocusedWindow(windowSecond);
2313
2314 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002315 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2316 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002317
2318 // Focused window should receive event.
2319 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2320 windowTop->assertNoEvents();
2321}
2322
2323TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
2324 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2325 sp<FakeWindowHandle> window =
2326 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2327 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2328
2329 window->setFocusable(true);
2330 // Release channel for window is no longer valid.
2331 window->releaseChannel();
2332 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2333 setFocusedWindow(window);
2334
2335 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002336 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2337 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002338
2339 // window channel is invalid, so it should not receive any input event.
2340 window->assertNoEvents();
2341}
2342
2343TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
2344 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2345 sp<FakeWindowHandle> window =
2346 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2347 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2348
2349 // Window is not focusable.
2350 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2351 setFocusedWindow(window);
2352
2353 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002354 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2355 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002356
2357 // window is invalid, so it should not receive any input event.
2358 window->assertNoEvents();
2359}
2360
2361TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
2362 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2363 sp<FakeWindowHandle> windowTop =
2364 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2365 sp<FakeWindowHandle> windowSecond =
2366 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2367 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2368
2369 windowTop->setFocusable(true);
2370 windowSecond->setFocusable(true);
2371 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2372 setFocusedWindow(windowTop);
2373 windowTop->consumeFocusEvent(true);
2374
2375 setFocusedWindow(windowSecond, windowTop);
2376 windowSecond->consumeFocusEvent(true);
2377 windowTop->consumeFocusEvent(false);
2378
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002379 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2380 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002381
2382 // Focused window should receive event.
2383 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2384}
2385
2386TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
2387 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2388 sp<FakeWindowHandle> windowTop =
2389 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2390 sp<FakeWindowHandle> windowSecond =
2391 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2392 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2393
2394 windowTop->setFocusable(true);
2395 windowSecond->setFocusable(true);
2396 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2397 setFocusedWindow(windowSecond, windowTop);
2398
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002399 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2400 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002401
2402 // Event should be dropped.
2403 windowTop->assertNoEvents();
2404 windowSecond->assertNoEvents();
2405}
2406
2407TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
2408 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2409 sp<FakeWindowHandle> window =
2410 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2411 sp<FakeWindowHandle> previousFocusedWindow =
2412 new FakeWindowHandle(application, mDispatcher, "previousFocusedWindow",
2413 ADISPLAY_ID_DEFAULT);
2414 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2415
2416 window->setFocusable(true);
2417 previousFocusedWindow->setFocusable(true);
2418 window->setVisible(false);
2419 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
2420 setFocusedWindow(previousFocusedWindow);
2421 previousFocusedWindow->consumeFocusEvent(true);
2422
2423 // Requesting focus on invisible window takes focus from currently focused window.
2424 setFocusedWindow(window);
2425 previousFocusedWindow->consumeFocusEvent(false);
2426
2427 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002428 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07002429 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002430 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07002431
2432 // Window does not get focus event or key down.
2433 window->assertNoEvents();
2434
2435 // Window becomes visible.
2436 window->setVisible(true);
2437 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2438
2439 // Window receives focus event.
2440 window->consumeFocusEvent(true);
2441 // Focused window receives key down.
2442 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2443}
2444
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002445/**
2446 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
2447 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
2448 * of the 'slipperyEnterWindow'.
2449 *
2450 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
2451 * a way so that the touched location is no longer covered by the top window.
2452 *
2453 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
2454 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
2455 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
2456 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
2457 * with ACTION_DOWN).
2458 * Thus, the touch has been transferred from the top window into the bottom window, because the top
2459 * window moved itself away from the touched location and had Flag::SLIPPERY.
2460 *
2461 * Even though the top window moved away from the touched location, it is still obscuring the bottom
2462 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
2463 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
2464 *
2465 * In this test, we ensure that the event received by the bottom window has
2466 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
2467 */
2468TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
2469 constexpr int32_t SLIPPERY_PID = INJECTOR_PID + 1;
2470 constexpr int32_t SLIPPERY_UID = INJECTOR_UID + 1;
2471
2472 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2473 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2474
2475 sp<FakeWindowHandle> slipperyExitWindow =
2476 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2477 slipperyExitWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2478 InputWindowInfo::Flag::SLIPPERY);
2479 // Make sure this one overlaps the bottom window
2480 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
2481 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
2482 // one. Windows with the same owner are not considered to be occluding each other.
2483 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
2484
2485 sp<FakeWindowHandle> slipperyEnterWindow =
2486 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2487 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
2488
2489 mDispatcher->setInputWindows(
2490 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
2491
2492 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
2493 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2494 ADISPLAY_ID_DEFAULT, {{50, 50}});
2495 mDispatcher->notifyMotion(&args);
2496 slipperyExitWindow->consumeMotionDown();
2497 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
2498 mDispatcher->setInputWindows(
2499 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
2500
2501 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2502 ADISPLAY_ID_DEFAULT, {{51, 51}});
2503 mDispatcher->notifyMotion(&args);
2504
2505 slipperyExitWindow->consumeMotionCancel();
2506
2507 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
2508 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
2509}
2510
Garfield Tan1c7bc862020-01-28 13:24:04 -08002511class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
2512protected:
2513 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
2514 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
2515
Chris Yea209fde2020-07-22 13:54:51 -07002516 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002517 sp<FakeWindowHandle> mWindow;
2518
2519 virtual void SetUp() override {
2520 mFakePolicy = new FakeInputDispatcherPolicy();
2521 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
2522 mDispatcher = new InputDispatcher(mFakePolicy);
2523 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
2524 ASSERT_EQ(OK, mDispatcher->start());
2525
2526 setUpWindow();
2527 }
2528
2529 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07002530 mApp = std::make_shared<FakeApplicationHandle>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08002531 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2532
Vishnu Nair47074b82020-08-14 11:54:47 -07002533 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002534 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002535 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002536 mWindow->consumeFocusEvent(true);
2537 }
2538
Chris Ye2ad95392020-09-01 13:44:44 -07002539 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08002540 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07002541 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002542 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
2543 mDispatcher->notifyKey(&keyArgs);
2544
2545 // Window should receive key down event.
2546 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2547 }
2548
2549 void expectKeyRepeatOnce(int32_t repeatCount) {
2550 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
2551 InputEvent* repeatEvent = mWindow->consume();
2552 ASSERT_NE(nullptr, repeatEvent);
2553
2554 uint32_t eventType = repeatEvent->getType();
2555 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
2556
2557 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
2558 uint32_t eventAction = repeatKeyEvent->getAction();
2559 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
2560 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
2561 }
2562
Chris Ye2ad95392020-09-01 13:44:44 -07002563 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08002564 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07002565 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002566 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
2567 mDispatcher->notifyKey(&keyArgs);
2568
2569 // Window should receive key down event.
2570 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
2571 0 /*expectedFlags*/);
2572 }
2573};
2574
2575TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Chris Ye2ad95392020-09-01 13:44:44 -07002576 sendAndConsumeKeyDown(1 /* deviceId */);
2577 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2578 expectKeyRepeatOnce(repeatCount);
2579 }
2580}
2581
2582TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
2583 sendAndConsumeKeyDown(1 /* deviceId */);
2584 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2585 expectKeyRepeatOnce(repeatCount);
2586 }
2587 sendAndConsumeKeyDown(2 /* deviceId */);
2588 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08002589 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2590 expectKeyRepeatOnce(repeatCount);
2591 }
2592}
2593
2594TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Chris Ye2ad95392020-09-01 13:44:44 -07002595 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002596 expectKeyRepeatOnce(1 /*repeatCount*/);
Chris Ye2ad95392020-09-01 13:44:44 -07002597 sendAndConsumeKeyUp(1 /* deviceId */);
2598 mWindow->assertNoEvents();
2599}
2600
2601TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
2602 sendAndConsumeKeyDown(1 /* deviceId */);
2603 expectKeyRepeatOnce(1 /*repeatCount*/);
2604 sendAndConsumeKeyDown(2 /* deviceId */);
2605 expectKeyRepeatOnce(1 /*repeatCount*/);
2606 // Stale key up from device 1.
2607 sendAndConsumeKeyUp(1 /* deviceId */);
2608 // Device 2 is still down, keep repeating
2609 expectKeyRepeatOnce(2 /*repeatCount*/);
2610 expectKeyRepeatOnce(3 /*repeatCount*/);
2611 // Device 2 key up
2612 sendAndConsumeKeyUp(2 /* deviceId */);
2613 mWindow->assertNoEvents();
2614}
2615
2616TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
2617 sendAndConsumeKeyDown(1 /* deviceId */);
2618 expectKeyRepeatOnce(1 /*repeatCount*/);
2619 sendAndConsumeKeyDown(2 /* deviceId */);
2620 expectKeyRepeatOnce(1 /*repeatCount*/);
2621 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
2622 sendAndConsumeKeyUp(2 /* deviceId */);
2623 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08002624 mWindow->assertNoEvents();
2625}
2626
2627TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Chris Ye2ad95392020-09-01 13:44:44 -07002628 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002629 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2630 InputEvent* repeatEvent = mWindow->consume();
2631 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2632 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
2633 IdGenerator::getSource(repeatEvent->getId()));
2634 }
2635}
2636
2637TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Chris Ye2ad95392020-09-01 13:44:44 -07002638 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002639
2640 std::unordered_set<int32_t> idSet;
2641 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2642 InputEvent* repeatEvent = mWindow->consume();
2643 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2644 int32_t id = repeatEvent->getId();
2645 EXPECT_EQ(idSet.end(), idSet.find(id));
2646 idSet.insert(id);
2647 }
2648}
2649
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002650/* Test InputDispatcher for MultiDisplay */
2651class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
2652public:
2653 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002654 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002655 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08002656
Chris Yea209fde2020-07-22 13:54:51 -07002657 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002658 windowInPrimary =
2659 new FakeWindowHandle(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002660
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002661 // Set focus window for primary display, but focused display would be second one.
2662 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07002663 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002664 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002665 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002666 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08002667
Chris Yea209fde2020-07-22 13:54:51 -07002668 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002669 windowInSecondary =
2670 new FakeWindowHandle(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002671 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002672 // Set focus display to second one.
2673 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
2674 // Set focus window for second display.
2675 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07002676 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002677 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002678 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002679 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002680 }
2681
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002682 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002683 InputDispatcherTest::TearDown();
2684
Chris Yea209fde2020-07-22 13:54:51 -07002685 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002686 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07002687 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002688 windowInSecondary.clear();
2689 }
2690
2691protected:
Chris Yea209fde2020-07-22 13:54:51 -07002692 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002693 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07002694 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002695 sp<FakeWindowHandle> windowInSecondary;
2696};
2697
2698TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
2699 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2701 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2702 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002703 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08002704 windowInSecondary->assertNoEvents();
2705
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002706 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2708 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
2709 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08002710 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002711 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08002712}
2713
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002714TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08002715 // Test inject a key down with display id specified.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2717 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002718 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08002719 windowInSecondary->assertNoEvents();
2720
2721 // Test inject a key down without display id specified.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002722 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2723 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08002724 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002725 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08002726
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002727 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002728 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08002729
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002730 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002731 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
2732 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08002733
2734 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002735 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2736 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08002737 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002738 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08002739 windowInSecondary->assertNoEvents();
2740}
2741
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002742// Test per-display input monitors for motion event.
2743TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08002744 FakeMonitorReceiver monitorInPrimary =
2745 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2746 FakeMonitorReceiver monitorInSecondary =
2747 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002748
2749 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2751 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2752 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002753 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002754 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002755 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002756 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002757
2758 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2760 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
2761 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002762 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002763 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002764 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08002765 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002766
2767 // Test inject a non-pointer motion event.
2768 // If specific a display, it will dispatch to the focused window of particular display,
2769 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2771 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
2772 << "Inject motion 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->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002776 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002777}
2778
2779// Test per-display input monitors for key event.
2780TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002781 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08002782 FakeMonitorReceiver monitorInPrimary =
2783 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2784 FakeMonitorReceiver monitorInSecondary =
2785 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002786
2787 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002788 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2789 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002790 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002791 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002792 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002793 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002794}
2795
Vishnu Nair958da932020-08-21 17:12:37 -07002796TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
2797 sp<FakeWindowHandle> secondWindowInPrimary =
2798 new FakeWindowHandle(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2799 secondWindowInPrimary->setFocusable(true);
2800 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
2801 setFocusedWindow(secondWindowInPrimary);
2802 windowInPrimary->consumeFocusEvent(false);
2803 secondWindowInPrimary->consumeFocusEvent(true);
2804
2805 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002806 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2807 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002808 windowInPrimary->assertNoEvents();
2809 windowInSecondary->assertNoEvents();
2810 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2811}
2812
Jackal Guof9696682018-10-05 12:23:23 +08002813class InputFilterTest : public InputDispatcherTest {
2814protected:
2815 static constexpr int32_t SECOND_DISPLAY_ID = 1;
2816
2817 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
2818 NotifyMotionArgs motionArgs;
2819
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002820 motionArgs =
2821 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08002822 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002823 motionArgs =
2824 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08002825 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002826 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002827 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002828 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002829 } else {
2830 mFakePolicy->assertFilterInputEventWasNotCalled();
2831 }
2832 }
2833
2834 void testNotifyKey(bool expectToBeFiltered) {
2835 NotifyKeyArgs keyArgs;
2836
2837 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2838 mDispatcher->notifyKey(&keyArgs);
2839 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
2840 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002841 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002842
2843 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002844 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002845 } else {
2846 mFakePolicy->assertFilterInputEventWasNotCalled();
2847 }
2848 }
2849};
2850
2851// Test InputFilter for MotionEvent
2852TEST_F(InputFilterTest, MotionEvent_InputFilter) {
2853 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
2854 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2855 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2856
2857 // Enable InputFilter
2858 mDispatcher->setInputFilterEnabled(true);
2859 // Test touch on both primary and second display, and check if both events are filtered.
2860 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
2861 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
2862
2863 // Disable InputFilter
2864 mDispatcher->setInputFilterEnabled(false);
2865 // Test touch on both primary and second display, and check if both events aren't filtered.
2866 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2867 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2868}
2869
2870// Test InputFilter for KeyEvent
2871TEST_F(InputFilterTest, KeyEvent_InputFilter) {
2872 // Since the InputFilter is disabled by default, check if key event aren't filtered.
2873 testNotifyKey(/*expectToBeFiltered*/ false);
2874
2875 // Enable InputFilter
2876 mDispatcher->setInputFilterEnabled(true);
2877 // Send a key event, and check if it is filtered.
2878 testNotifyKey(/*expectToBeFiltered*/ true);
2879
2880 // Disable InputFilter
2881 mDispatcher->setInputFilterEnabled(false);
2882 // Send a key event, and check if it isn't filtered.
2883 testNotifyKey(/*expectToBeFiltered*/ false);
2884}
2885
chaviwfd6d3512019-03-25 13:23:49 -07002886class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002887 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07002888 InputDispatcherTest::SetUp();
2889
Chris Yea209fde2020-07-22 13:54:51 -07002890 std::shared_ptr<FakeApplicationHandle> application =
2891 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002892 mUnfocusedWindow =
2893 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002894 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
2895 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2896 // window.
Michael Wright44753b12020-07-08 13:48:11 +01002897 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002898
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002899 mFocusedWindow =
2900 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2901 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01002902 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002903
2904 // Set focused application.
2905 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002906 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07002907
2908 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002909 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002910 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002911 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07002912 }
2913
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002914 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07002915 InputDispatcherTest::TearDown();
2916
2917 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002918 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07002919 }
2920
2921protected:
2922 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002923 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002924 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07002925};
2926
2927// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2928// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
2929// the onPointerDownOutsideFocus callback.
2930TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002932 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2933 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002934 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002935 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002936
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002937 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07002938 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
2939}
2940
2941// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
2942// DOWN on the window that doesn't have focus. Ensure no window received the
2943// onPointerDownOutsideFocus callback.
2944TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002946 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002947 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002948 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002949
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002950 ASSERT_TRUE(mDispatcher->waitForIdle());
2951 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002952}
2953
2954// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
2955// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
2956TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002957 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2958 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002959 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002960
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002961 ASSERT_TRUE(mDispatcher->waitForIdle());
2962 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002963}
2964
2965// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2966// DOWN on the window that already has focus. Ensure no window received the
2967// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002968TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002969 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002970 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002971 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002972 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002973 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002974
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002975 ASSERT_TRUE(mDispatcher->waitForIdle());
2976 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002977}
2978
chaviwaf87b3e2019-10-01 16:59:28 -07002979// These tests ensures we can send touch events to a single client when there are multiple input
2980// windows that point to the same client token.
2981class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
2982 virtual void SetUp() override {
2983 InputDispatcherTest::SetUp();
2984
Chris Yea209fde2020-07-22 13:54:51 -07002985 std::shared_ptr<FakeApplicationHandle> application =
2986 std::make_shared<FakeApplicationHandle>();
chaviwaf87b3e2019-10-01 16:59:28 -07002987 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
2988 ADISPLAY_ID_DEFAULT);
2989 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
2990 // 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 +01002991 mWindow1->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2992 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002993 mWindow1->setFrame(Rect(0, 0, 100, 100));
2994
2995 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
2996 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
Michael Wright44753b12020-07-08 13:48:11 +01002997 mWindow2->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2998 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002999 mWindow2->setFrame(Rect(100, 100, 200, 200));
3000
Arthur Hung72d8dc32020-03-28 00:48:39 +00003001 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07003002 }
3003
3004protected:
3005 sp<FakeWindowHandle> mWindow1;
3006 sp<FakeWindowHandle> mWindow2;
3007
3008 // Helper function to convert the point from screen coordinates into the window's space
3009 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07003010 vec2 vals = windowInfo->transform.transform(point.x, point.y);
3011 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07003012 }
3013
3014 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
3015 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003016 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07003017 InputEvent* event = window->consume();
3018
3019 ASSERT_NE(nullptr, event) << name.c_str()
3020 << ": consumer should have returned non-NULL event.";
3021
3022 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
3023 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
3024 << " event, got " << inputEventTypeToString(event->getType()) << " event";
3025
3026 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
3027 EXPECT_EQ(expectedAction, motionEvent.getAction());
3028
3029 for (size_t i = 0; i < points.size(); i++) {
3030 float expectedX = points[i].x;
3031 float expectedY = points[i].y;
3032
3033 EXPECT_EQ(expectedX, motionEvent.getX(i))
3034 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
3035 << ", got " << motionEvent.getX(i);
3036 EXPECT_EQ(expectedY, motionEvent.getY(i))
3037 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
3038 << ", got " << motionEvent.getY(i);
3039 }
3040 }
chaviw9eaa22c2020-07-01 16:21:27 -07003041
3042 void touchAndAssertPositions(int32_t action, std::vector<PointF> touchedPoints,
3043 std::vector<PointF> expectedPoints) {
3044 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
3045 ADISPLAY_ID_DEFAULT, touchedPoints);
3046 mDispatcher->notifyMotion(&motionArgs);
3047
3048 // Always consume from window1 since it's the window that has the InputReceiver
3049 consumeMotionEvent(mWindow1, action, expectedPoints);
3050 }
chaviwaf87b3e2019-10-01 16:59:28 -07003051};
3052
3053TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
3054 // Touch Window 1
3055 PointF touchedPoint = {10, 10};
3056 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003057 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003058
3059 // 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});
chaviwaf87b3e2019-10-01 16:59:28 -07003066}
3067
chaviw9eaa22c2020-07-01 16:21:27 -07003068TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
3069 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07003070 mWindow2->setWindowScale(0.5f, 0.5f);
3071
3072 // Touch Window 1
3073 PointF touchedPoint = {10, 10};
3074 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003075 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003076 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07003077 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003078
3079 // Touch Window 2
3080 touchedPoint = {150, 150};
3081 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003082 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
3083 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003084
chaviw9eaa22c2020-07-01 16:21:27 -07003085 // Update the transform so rotation is set
3086 mWindow2->setWindowTransform(0, -1, 1, 0);
3087 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
3088 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003089}
3090
chaviw9eaa22c2020-07-01 16:21:27 -07003091TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003092 mWindow2->setWindowScale(0.5f, 0.5f);
3093
3094 // Touch Window 1
3095 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3096 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003097 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003098
3099 // Touch Window 2
3100 int32_t actionPointerDown =
3101 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003102 touchedPoints.push_back(PointF{150, 150});
3103 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3104 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003105
chaviw9eaa22c2020-07-01 16:21:27 -07003106 // Release Window 2
3107 int32_t actionPointerUp =
3108 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3109 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
3110 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003111
chaviw9eaa22c2020-07-01 16:21:27 -07003112 // Update the transform so rotation is set for Window 2
3113 mWindow2->setWindowTransform(0, -1, 1, 0);
3114 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3115 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003116}
3117
chaviw9eaa22c2020-07-01 16:21:27 -07003118TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003119 mWindow2->setWindowScale(0.5f, 0.5f);
3120
3121 // Touch Window 1
3122 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3123 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003124 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003125
3126 // Touch Window 2
3127 int32_t actionPointerDown =
3128 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003129 touchedPoints.push_back(PointF{150, 150});
3130 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003131
chaviw9eaa22c2020-07-01 16:21:27 -07003132 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003133
3134 // Move both windows
3135 touchedPoints = {{20, 20}, {175, 175}};
3136 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3137 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3138
chaviw9eaa22c2020-07-01 16:21:27 -07003139 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003140
chaviw9eaa22c2020-07-01 16:21:27 -07003141 // Release Window 2
3142 int32_t actionPointerUp =
3143 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3144 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
3145 expectedPoints.pop_back();
3146
3147 // Touch Window 2
3148 mWindow2->setWindowTransform(0, -1, 1, 0);
3149 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3150 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
3151
3152 // Move both windows
3153 touchedPoints = {{20, 20}, {175, 175}};
3154 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3155 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3156
3157 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003158}
3159
3160TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
3161 mWindow1->setWindowScale(0.5f, 0.5f);
3162
3163 // Touch Window 1
3164 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3165 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003166 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003167
3168 // Touch Window 2
3169 int32_t actionPointerDown =
3170 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003171 touchedPoints.push_back(PointF{150, 150});
3172 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003173
chaviw9eaa22c2020-07-01 16:21:27 -07003174 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003175
3176 // Move both windows
3177 touchedPoints = {{20, 20}, {175, 175}};
3178 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3179 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3180
chaviw9eaa22c2020-07-01 16:21:27 -07003181 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003182}
3183
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003184class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
3185 virtual void SetUp() override {
3186 InputDispatcherTest::SetUp();
3187
Chris Yea209fde2020-07-22 13:54:51 -07003188 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003189 mApplication->setDispatchingTimeout(20ms);
3190 mWindow =
3191 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3192 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05003193 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07003194 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003195 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3196 // window.
Michael Wright44753b12020-07-08 13:48:11 +01003197 mWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003198
3199 // Set focused application.
3200 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
3201
3202 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003203 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003204 mWindow->consumeFocusEvent(true);
3205 }
3206
3207 virtual void TearDown() override {
3208 InputDispatcherTest::TearDown();
3209 mWindow.clear();
3210 }
3211
3212protected:
Chris Yea209fde2020-07-22 13:54:51 -07003213 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003214 sp<FakeWindowHandle> mWindow;
3215 static constexpr PointF WINDOW_LOCATION = {20, 20};
3216
3217 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003218 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003219 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3220 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003222 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3223 WINDOW_LOCATION));
3224 }
3225};
3226
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003227// Send a tap and respond, which should not cause an ANR.
3228TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
3229 tapOnWindow();
3230 mWindow->consumeMotionDown();
3231 mWindow->consumeMotionUp();
3232 ASSERT_TRUE(mDispatcher->waitForIdle());
3233 mFakePolicy->assertNotifyAnrWasNotCalled();
3234}
3235
3236// Send a regular key and respond, which should not cause an ANR.
3237TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003239 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
3240 ASSERT_TRUE(mDispatcher->waitForIdle());
3241 mFakePolicy->assertNotifyAnrWasNotCalled();
3242}
3243
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05003244TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
3245 mWindow->setFocusable(false);
3246 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3247 mWindow->consumeFocusEvent(false);
3248
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003249 InputEventInjectionResult result =
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05003250 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003251 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
3252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05003253 // Key will not go to window because we have no focused window.
3254 // The 'no focused window' ANR timer should start instead.
3255
3256 // Now, the focused application goes away.
3257 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
3258 // The key should get dropped and there should be no ANR.
3259
3260 ASSERT_TRUE(mDispatcher->waitForIdle());
3261 mFakePolicy->assertNotifyAnrWasNotCalled();
3262}
3263
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003264// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003265// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
3266// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003267TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003269 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3270 WINDOW_LOCATION));
3271
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003272 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
3273 ASSERT_TRUE(sequenceNum);
3274 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003275 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003276
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003277 mWindow->finishEvent(*sequenceNum);
3278 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
3279 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003280 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003281 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003282}
3283
3284// Send a key to the app and have the app not respond right away.
3285TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
3286 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003287 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003288 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
3289 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003290 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003291 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003292 ASSERT_TRUE(mDispatcher->waitForIdle());
3293}
3294
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003295// We have a focused application, but no focused window
3296TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003297 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003298 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3299 mWindow->consumeFocusEvent(false);
3300
3301 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003302 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003303 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3304 WINDOW_LOCATION));
3305 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
3306 mDispatcher->waitForIdle();
3307 mFakePolicy->assertNotifyAnrWasNotCalled();
3308
3309 // Once a focused event arrives, we get an ANR for this application
3310 // We specify the injection timeout to be smaller than the application timeout, to ensure that
3311 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003312 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003313 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003314 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3315 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003316 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003317 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003318 ASSERT_TRUE(mDispatcher->waitForIdle());
3319}
3320
3321// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003322// Make sure that we don't notify policy twice about the same ANR.
3323TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003324 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003325 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3326 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003327
3328 // Once a focused event arrives, we get an ANR for this application
3329 // We specify the injection timeout to be smaller than the application timeout, to ensure that
3330 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003331 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003332 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003333 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3334 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003335 const std::chrono::duration appTimeout =
3336 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003337 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003338
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003339 std::this_thread::sleep_for(appTimeout);
3340 // ANR should not be raised again. It is up to policy to do that if it desires.
3341 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003342
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003343 // If we now get a focused window, the ANR should stop, but the policy handles that via
3344 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003345 ASSERT_TRUE(mDispatcher->waitForIdle());
3346}
3347
3348// We have a focused application, but no focused window
3349TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003350 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003351 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3352 mWindow->consumeFocusEvent(false);
3353
3354 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003355 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003356 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003357 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3358 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003359
3360 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003361 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003362
3363 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003364 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003365 ASSERT_TRUE(mDispatcher->waitForIdle());
3366 mWindow->assertNoEvents();
3367}
3368
3369/**
3370 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
3371 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
3372 * If we process 1 of the events, but ANR on the second event with the same timestamp,
3373 * the ANR mechanism should still work.
3374 *
3375 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
3376 * DOWN event, while not responding on the second one.
3377 */
3378TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
3379 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
3380 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3381 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
3382 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
3383 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003384 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003385
3386 // Now send ACTION_UP, with identical timestamp
3387 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3388 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
3389 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
3390 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003391 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003392
3393 // We have now sent down and up. Let's consume first event and then ANR on the second.
3394 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
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
3399// If an app is not responding to a key event, gesture monitors should continue to receive
3400// new motion events
3401TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
3402 FakeMonitorReceiver monitor =
3403 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
3404 true /*isGestureMonitor*/);
3405
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003406 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3407 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003408 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003409 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003410
3411 // Stuck on the ACTION_UP
3412 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003413 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003414
3415 // New tap will go to the gesture monitor, but not to the window
3416 tapOnWindow();
3417 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3418 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3419
3420 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
3421 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003422 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003423 mWindow->assertNoEvents();
3424 monitor.assertNoEvents();
3425}
3426
3427// If an app is not responding to a motion event, gesture monitors should continue to receive
3428// new motion events
3429TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
3430 FakeMonitorReceiver monitor =
3431 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
3432 true /*isGestureMonitor*/);
3433
3434 tapOnWindow();
3435 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3436 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3437
3438 mWindow->consumeMotionDown();
3439 // Stuck on the ACTION_UP
3440 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003441 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003442
3443 // New tap will go to the gesture monitor, but not to the window
3444 tapOnWindow();
3445 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3446 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3447
3448 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
3449 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003450 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003451 mWindow->assertNoEvents();
3452 monitor.assertNoEvents();
3453}
3454
3455// If a window is unresponsive, then you get anr. if the window later catches up and starts to
3456// process events, you don't get an anr. When the window later becomes unresponsive again, you
3457// get an ANR again.
3458// 1. tap -> block on ACTION_UP -> receive ANR
3459// 2. consume all pending events (= queue becomes healthy again)
3460// 3. tap again -> block on ACTION_UP again -> receive ANR second time
3461TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
3462 tapOnWindow();
3463
3464 mWindow->consumeMotionDown();
3465 // Block on ACTION_UP
3466 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003467 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003468 mWindow->consumeMotionUp(); // Now the connection should be healthy again
3469 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003470 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003471 mWindow->assertNoEvents();
3472
3473 tapOnWindow();
3474 mWindow->consumeMotionDown();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003475 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003476 mWindow->consumeMotionUp();
3477
3478 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003479 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003480 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003481 mWindow->assertNoEvents();
3482}
3483
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003484// If a connection remains unresponsive for a while, make sure policy is only notified once about
3485// it.
3486TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003487 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003488 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3489 WINDOW_LOCATION));
3490
3491 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003492 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003493 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003494 // 'notifyConnectionUnresponsive' should only be called once per connection
3495 mFakePolicy->assertNotifyAnrWasNotCalled();
3496 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003497 mWindow->consumeMotionDown();
3498 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
3499 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3500 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003501 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003502 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003503 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003504}
3505
3506/**
3507 * If a window is processing a motion event, and then a key event comes in, the key event should
3508 * not to to the focused window until the motion is processed.
3509 *
3510 * Warning!!!
3511 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
3512 * and the injection timeout that we specify when injecting the key.
3513 * We must have the injection timeout (10ms) be smaller than
3514 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
3515 *
3516 * If that value changes, this test should also change.
3517 */
3518TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
3519 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
3520 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3521
3522 tapOnWindow();
3523 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
3524 ASSERT_TRUE(downSequenceNum);
3525 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
3526 ASSERT_TRUE(upSequenceNum);
3527 // Don't finish the events yet, and send a key
3528 // Injection will "succeed" because we will eventually give up and send the key to the focused
3529 // window even if motions are still being processed. But because the injection timeout is short,
3530 // we will receive INJECTION_TIMED_OUT as the result.
3531
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003532 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003533 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003534 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3535 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003536 // Key will not be sent to the window, yet, because the window is still processing events
3537 // and the key remains pending, waiting for the touch events to be processed
3538 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
3539 ASSERT_FALSE(keySequenceNum);
3540
3541 std::this_thread::sleep_for(500ms);
3542 // if we wait long enough though, dispatcher will give up, and still send the key
3543 // to the focused window, even though we have not yet finished the motion event
3544 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3545 mWindow->finishEvent(*downSequenceNum);
3546 mWindow->finishEvent(*upSequenceNum);
3547}
3548
3549/**
3550 * If a window is processing a motion event, and then a key event comes in, the key event should
3551 * not go to the focused window until the motion is processed.
3552 * If then a new motion comes in, then the pending key event should be going to the currently
3553 * focused window right away.
3554 */
3555TEST_F(InputDispatcherSingleWindowAnr,
3556 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
3557 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
3558 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3559
3560 tapOnWindow();
3561 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
3562 ASSERT_TRUE(downSequenceNum);
3563 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
3564 ASSERT_TRUE(upSequenceNum);
3565 // Don't finish the events yet, and send a key
3566 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003568 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003569 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003570 // At this point, key is still pending, and should not be sent to the application yet.
3571 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
3572 ASSERT_FALSE(keySequenceNum);
3573
3574 // Now tap down again. It should cause the pending key to go to the focused window right away.
3575 tapOnWindow();
3576 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
3577 // the other events yet. We can finish events in any order.
3578 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
3579 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
3580 mWindow->consumeMotionDown();
3581 mWindow->consumeMotionUp();
3582 mWindow->assertNoEvents();
3583}
3584
3585class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
3586 virtual void SetUp() override {
3587 InputDispatcherTest::SetUp();
3588
Chris Yea209fde2020-07-22 13:54:51 -07003589 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003590 mApplication->setDispatchingTimeout(10ms);
3591 mUnfocusedWindow =
3592 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
3593 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
3594 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3595 // window.
3596 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Michael Wright44753b12020-07-08 13:48:11 +01003597 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3598 InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
3599 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003600
3601 mFocusedWindow =
3602 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05003603 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003604 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01003605 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3606 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003607
3608 // Set focused application.
3609 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07003610 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003611
3612 // Expect one focus window exist in display.
3613 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003614 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003615 mFocusedWindow->consumeFocusEvent(true);
3616 }
3617
3618 virtual void TearDown() override {
3619 InputDispatcherTest::TearDown();
3620
3621 mUnfocusedWindow.clear();
3622 mFocusedWindow.clear();
3623 }
3624
3625protected:
Chris Yea209fde2020-07-22 13:54:51 -07003626 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003627 sp<FakeWindowHandle> mUnfocusedWindow;
3628 sp<FakeWindowHandle> mFocusedWindow;
3629 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
3630 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
3631 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
3632
3633 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
3634
3635 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
3636
3637private:
3638 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003640 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3641 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003643 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3644 location));
3645 }
3646};
3647
3648// If we have 2 windows that are both unresponsive, the one with the shortest timeout
3649// should be ANR'd first.
3650TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003652 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3653 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003654 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003655 mFocusedWindow->consumeMotionDown();
3656 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3657 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3658 // We consumed all events, so no ANR
3659 ASSERT_TRUE(mDispatcher->waitForIdle());
3660 mFakePolicy->assertNotifyAnrWasNotCalled();
3661
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003662 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003663 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3664 FOCUSED_WINDOW_LOCATION));
3665 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
3666 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003667
3668 const std::chrono::duration timeout =
3669 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003670 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003671 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
3672 // sequence to make it consistent
3673 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003674 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003675 mFocusedWindow->consumeMotionDown();
3676 // This cancel is generated because the connection was unresponsive
3677 mFocusedWindow->consumeMotionCancel();
3678 mFocusedWindow->assertNoEvents();
3679 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003680 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003681 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003682 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003683}
3684
3685// If we have 2 windows with identical timeouts that are both unresponsive,
3686// it doesn't matter which order they should have ANR.
3687// But we should receive ANR for both.
3688TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
3689 // Set the timeout for unfocused window to match the focused window
3690 mUnfocusedWindow->setDispatchingTimeout(10ms);
3691 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3692
3693 tapOnFocusedWindow();
3694 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003695 sp<IBinder> anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms);
3696 sp<IBinder> anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003697
3698 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003699 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
3700 mFocusedWindow->getToken() == anrConnectionToken2);
3701 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
3702 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003703
3704 ASSERT_TRUE(mDispatcher->waitForIdle());
3705 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003706
3707 mFocusedWindow->consumeMotionDown();
3708 mFocusedWindow->consumeMotionUp();
3709 mUnfocusedWindow->consumeMotionOutside();
3710
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003711 sp<IBinder> responsiveToken1 = mFakePolicy->getResponsiveWindowToken();
3712 sp<IBinder> responsiveToken2 = mFakePolicy->getResponsiveWindowToken();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003713
3714 // Both applications should be marked as responsive, in any order
3715 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
3716 mFocusedWindow->getToken() == responsiveToken2);
3717 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
3718 mUnfocusedWindow->getToken() == responsiveToken2);
3719 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003720}
3721
3722// If a window is already not responding, the second tap on the same window should be ignored.
3723// We should also log an error to account for the dropped event (not tested here).
3724// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
3725TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
3726 tapOnFocusedWindow();
3727 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3728 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3729 // Receive the events, but don't respond
3730 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
3731 ASSERT_TRUE(downEventSequenceNum);
3732 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
3733 ASSERT_TRUE(upEventSequenceNum);
3734 const std::chrono::duration timeout =
3735 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003736 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003737
3738 // Tap once again
3739 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003740 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003741 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3742 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003743 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003744 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3745 FOCUSED_WINDOW_LOCATION));
3746 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
3747 // valid touch target
3748 mUnfocusedWindow->assertNoEvents();
3749
3750 // Consume the first tap
3751 mFocusedWindow->finishEvent(*downEventSequenceNum);
3752 mFocusedWindow->finishEvent(*upEventSequenceNum);
3753 ASSERT_TRUE(mDispatcher->waitForIdle());
3754 // The second tap did not go to the focused window
3755 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003756 // Since all events are finished, connection should be deemed healthy again
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003757 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003758 mFakePolicy->assertNotifyAnrWasNotCalled();
3759}
3760
3761// If you tap outside of all windows, there will not be ANR
3762TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003763 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003764 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3765 LOCATION_OUTSIDE_ALL_WINDOWS));
3766 ASSERT_TRUE(mDispatcher->waitForIdle());
3767 mFakePolicy->assertNotifyAnrWasNotCalled();
3768}
3769
3770// Since the focused window is paused, tapping on it should not produce any events
3771TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
3772 mFocusedWindow->setPaused(true);
3773 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3774
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003775 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003776 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3777 FOCUSED_WINDOW_LOCATION));
3778
3779 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
3780 ASSERT_TRUE(mDispatcher->waitForIdle());
3781 // Should not ANR because the window is paused, and touches shouldn't go to it
3782 mFakePolicy->assertNotifyAnrWasNotCalled();
3783
3784 mFocusedWindow->assertNoEvents();
3785 mUnfocusedWindow->assertNoEvents();
3786}
3787
3788/**
3789 * If a window is processing a motion event, and then a key event comes in, the key event should
3790 * not to to the focused window until the motion is processed.
3791 * If a different window becomes focused at this time, the key should go to that window instead.
3792 *
3793 * Warning!!!
3794 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
3795 * and the injection timeout that we specify when injecting the key.
3796 * We must have the injection timeout (10ms) be smaller than
3797 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
3798 *
3799 * If that value changes, this test should also change.
3800 */
3801TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
3802 // Set a long ANR timeout to prevent it from triggering
3803 mFocusedWindow->setDispatchingTimeout(2s);
3804 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3805
3806 tapOnUnfocusedWindow();
3807 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
3808 ASSERT_TRUE(downSequenceNum);
3809 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
3810 ASSERT_TRUE(upSequenceNum);
3811 // Don't finish the events yet, and send a key
3812 // Injection will succeed because we will eventually give up and send the key to the focused
3813 // window even if motions are still being processed.
3814
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003815 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003816 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003817 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
3818 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003819 // Key will not be sent to the window, yet, because the window is still processing events
3820 // and the key remains pending, waiting for the touch events to be processed
3821 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
3822 ASSERT_FALSE(keySequenceNum);
3823
3824 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07003825 mFocusedWindow->setFocusable(false);
3826 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003827 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003828 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003829
3830 // Focus events should precede the key events
3831 mUnfocusedWindow->consumeFocusEvent(true);
3832 mFocusedWindow->consumeFocusEvent(false);
3833
3834 // Finish the tap events, which should unblock dispatcher
3835 mUnfocusedWindow->finishEvent(*downSequenceNum);
3836 mUnfocusedWindow->finishEvent(*upSequenceNum);
3837
3838 // Now that all queues are cleared and no backlog in the connections, the key event
3839 // can finally go to the newly focused "mUnfocusedWindow".
3840 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3841 mFocusedWindow->assertNoEvents();
3842 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003843 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003844}
3845
3846// When the touch stream is split across 2 windows, and one of them does not respond,
3847// then ANR should be raised and the touch should be canceled for the unresponsive window.
3848// The other window should not be affected by that.
3849TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
3850 // Touch Window 1
3851 NotifyMotionArgs motionArgs =
3852 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3853 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
3854 mDispatcher->notifyMotion(&motionArgs);
3855 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3856 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3857
3858 // Touch Window 2
3859 int32_t actionPointerDown =
3860 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3861
3862 motionArgs =
3863 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3864 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
3865 mDispatcher->notifyMotion(&motionArgs);
3866
3867 const std::chrono::duration timeout =
3868 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003869 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003870
3871 mUnfocusedWindow->consumeMotionDown();
3872 mFocusedWindow->consumeMotionDown();
3873 // Focused window may or may not receive ACTION_MOVE
3874 // But it should definitely receive ACTION_CANCEL due to the ANR
3875 InputEvent* event;
3876 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
3877 ASSERT_TRUE(moveOrCancelSequenceNum);
3878 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
3879 ASSERT_NE(nullptr, event);
3880 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
3881 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
3882 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
3883 mFocusedWindow->consumeMotionCancel();
3884 } else {
3885 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
3886 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003887 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003888 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003889
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003890 mUnfocusedWindow->assertNoEvents();
3891 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003892 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003893}
3894
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003895/**
3896 * If we have no focused window, and a key comes in, we start the ANR timer.
3897 * The focused application should add a focused window before the timer runs out to prevent ANR.
3898 *
3899 * If the user touches another application during this time, the key should be dropped.
3900 * Next, if a new focused window comes in, without toggling the focused application,
3901 * then no ANR should occur.
3902 *
3903 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
3904 * but in some cases the policy may not update the focused application.
3905 */
3906TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
3907 std::shared_ptr<FakeApplicationHandle> focusedApplication =
3908 std::make_shared<FakeApplicationHandle>();
3909 focusedApplication->setDispatchingTimeout(60ms);
3910 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
3911 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
3912 mFocusedWindow->setFocusable(false);
3913
3914 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3915 mFocusedWindow->consumeFocusEvent(false);
3916
3917 // Send a key. The ANR timer should start because there is no focused window.
3918 // 'focusedApplication' will get blamed if this timer completes.
3919 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003920 InputEventInjectionResult result =
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003921 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003922 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
3923 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003924
3925 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
3926 // then the injected touches won't cause the focused event to get dropped.
3927 // The dispatcher only checks for whether the queue should be pruned upon queueing.
3928 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
3929 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
3930 // For this test, it means that the key would get delivered to the window once it becomes
3931 // focused.
3932 std::this_thread::sleep_for(10ms);
3933
3934 // Touch unfocused window. This should force the pending key to get dropped.
3935 NotifyMotionArgs motionArgs =
3936 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3937 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
3938 mDispatcher->notifyMotion(&motionArgs);
3939
3940 // We do not consume the motion right away, because that would require dispatcher to first
3941 // process (== drop) the key event, and by that time, ANR will be raised.
3942 // Set the focused window first.
3943 mFocusedWindow->setFocusable(true);
3944 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3945 setFocusedWindow(mFocusedWindow);
3946 mFocusedWindow->consumeFocusEvent(true);
3947 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
3948 // to another application. This could be a bug / behaviour in the policy.
3949
3950 mUnfocusedWindow->consumeMotionDown();
3951
3952 ASSERT_TRUE(mDispatcher->waitForIdle());
3953 // Should not ANR because we actually have a focused window. It was just added too slowly.
3954 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
3955}
3956
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05003957// These tests ensure we cannot send touch events to a window that's positioned behind a window
3958// that has feature NO_INPUT_CHANNEL.
3959// Layout:
3960// Top (closest to user)
3961// mNoInputWindow (above all windows)
3962// mBottomWindow
3963// Bottom (furthest from user)
3964class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
3965 virtual void SetUp() override {
3966 InputDispatcherTest::SetUp();
3967
3968 mApplication = std::make_shared<FakeApplicationHandle>();
3969 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
3970 "Window without input channel", ADISPLAY_ID_DEFAULT,
3971 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
3972
3973 mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
3974 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
3975 // It's perfectly valid for this window to not have an associated input channel
3976
3977 mBottomWindow = new FakeWindowHandle(mApplication, mDispatcher, "Bottom window",
3978 ADISPLAY_ID_DEFAULT);
3979 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
3980
3981 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
3982 }
3983
3984protected:
3985 std::shared_ptr<FakeApplicationHandle> mApplication;
3986 sp<FakeWindowHandle> mNoInputWindow;
3987 sp<FakeWindowHandle> mBottomWindow;
3988};
3989
3990TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
3991 PointF touchedPoint = {10, 10};
3992
3993 NotifyMotionArgs motionArgs =
3994 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3995 ADISPLAY_ID_DEFAULT, {touchedPoint});
3996 mDispatcher->notifyMotion(&motionArgs);
3997
3998 mNoInputWindow->assertNoEvents();
3999 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
4000 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
4001 // and therefore should prevent mBottomWindow from receiving touches
4002 mBottomWindow->assertNoEvents();
4003}
4004
4005/**
4006 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
4007 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
4008 */
4009TEST_F(InputDispatcherMultiWindowOcclusionTests,
4010 NoInputChannelFeature_DropsTouchesWithValidChannel) {
4011 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
4012 "Window with input channel and NO_INPUT_CHANNEL",
4013 ADISPLAY_ID_DEFAULT);
4014
4015 mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
4016 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
4017 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
4018
4019 PointF touchedPoint = {10, 10};
4020
4021 NotifyMotionArgs motionArgs =
4022 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4023 ADISPLAY_ID_DEFAULT, {touchedPoint});
4024 mDispatcher->notifyMotion(&motionArgs);
4025
4026 mNoInputWindow->assertNoEvents();
4027 mBottomWindow->assertNoEvents();
4028}
4029
Vishnu Nair958da932020-08-21 17:12:37 -07004030class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
4031protected:
4032 std::shared_ptr<FakeApplicationHandle> mApp;
4033 sp<FakeWindowHandle> mWindow;
4034 sp<FakeWindowHandle> mMirror;
4035
4036 virtual void SetUp() override {
4037 InputDispatcherTest::SetUp();
4038 mApp = std::make_shared<FakeApplicationHandle>();
4039 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
4040 mMirror = new FakeWindowHandle(mApp, mDispatcher, "TestWindowMirror", ADISPLAY_ID_DEFAULT,
4041 mWindow->getToken());
4042 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
4043 mWindow->setFocusable(true);
4044 mMirror->setFocusable(true);
4045 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4046 }
4047};
4048
4049TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
4050 // Request focus on a mirrored window
4051 setFocusedWindow(mMirror);
4052
4053 // window gets focused
4054 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004055 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4056 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004057 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
4058}
4059
4060// A focused & mirrored window remains focused only if the window and its mirror are both
4061// focusable.
4062TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
4063 setFocusedWindow(mMirror);
4064
4065 // window gets focused
4066 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4068 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004069 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4071 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004072 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4073
4074 mMirror->setFocusable(false);
4075 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4076
4077 // window loses focus since one of the windows associated with the token in not focusable
4078 mWindow->consumeFocusEvent(false);
4079
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004080 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4081 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004082 mWindow->assertNoEvents();
4083}
4084
4085// A focused & mirrored window remains focused until the window and its mirror both become
4086// invisible.
4087TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
4088 setFocusedWindow(mMirror);
4089
4090 // window gets focused
4091 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4093 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004094 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004095 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4096 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004097 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4098
4099 mMirror->setVisible(false);
4100 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4101
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004102 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4103 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004104 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004105 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4106 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004107 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4108
4109 mWindow->setVisible(false);
4110 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4111
4112 // window loses focus only after all windows associated with the token become invisible.
4113 mWindow->consumeFocusEvent(false);
4114
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004115 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4116 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004117 mWindow->assertNoEvents();
4118}
4119
4120// A focused & mirrored window remains focused until both windows are removed.
4121TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
4122 setFocusedWindow(mMirror);
4123
4124 // window gets focused
4125 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004126 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4127 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004128 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004129 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4130 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004131 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4132
4133 // single window is removed but the window token remains focused
4134 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
4135
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004136 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4137 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004138 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004139 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4140 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004141 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4142
4143 // Both windows are removed
4144 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
4145 mWindow->consumeFocusEvent(false);
4146
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004147 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4148 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004149 mWindow->assertNoEvents();
4150}
4151
4152// Focus request can be pending until one window becomes visible.
4153TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
4154 // Request focus on an invisible mirror.
4155 mWindow->setVisible(false);
4156 mMirror->setVisible(false);
4157 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4158 setFocusedWindow(mMirror);
4159
4160 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004161 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07004162 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004163 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07004164
4165 mMirror->setVisible(true);
4166 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4167
4168 // window gets focused
4169 mWindow->consumeFocusEvent(true);
4170 // window gets the pending key event
4171 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4172}
Prabir Pradhan99987712020-11-10 18:43:05 -08004173
4174class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
4175protected:
4176 std::shared_ptr<FakeApplicationHandle> mApp;
4177 sp<FakeWindowHandle> mWindow;
4178 sp<FakeWindowHandle> mSecondWindow;
4179
4180 void SetUp() override {
4181 InputDispatcherTest::SetUp();
4182 mApp = std::make_shared<FakeApplicationHandle>();
4183 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
4184 mWindow->setFocusable(true);
4185 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
4186 mSecondWindow->setFocusable(true);
4187
4188 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
4189 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
4190
4191 setFocusedWindow(mWindow);
4192 mWindow->consumeFocusEvent(true);
4193 }
4194
4195 void notifyPointerCaptureChanged(bool enabled) {
4196 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(enabled);
4197 mDispatcher->notifyPointerCaptureChanged(&args);
4198 }
4199
4200 void requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window, bool enabled) {
4201 mDispatcher->requestPointerCapture(window->getToken(), enabled);
4202 mFakePolicy->waitForSetPointerCapture(enabled);
4203 notifyPointerCaptureChanged(enabled);
4204 window->consumeCaptureEvent(enabled);
4205 }
4206};
4207
4208TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
4209 // Ensure that capture cannot be obtained for unfocused windows.
4210 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
4211 mFakePolicy->assertSetPointerCaptureNotCalled();
4212 mSecondWindow->assertNoEvents();
4213
4214 // Ensure that capture can be enabled from the focus window.
4215 requestAndVerifyPointerCapture(mWindow, true);
4216
4217 // Ensure that capture cannot be disabled from a window that does not have capture.
4218 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
4219 mFakePolicy->assertSetPointerCaptureNotCalled();
4220
4221 // Ensure that capture can be disabled from the window with capture.
4222 requestAndVerifyPointerCapture(mWindow, false);
4223}
4224
4225TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
4226 requestAndVerifyPointerCapture(mWindow, true);
4227
4228 setFocusedWindow(mSecondWindow);
4229
4230 // Ensure that the capture disabled event was sent first.
4231 mWindow->consumeCaptureEvent(false);
4232 mWindow->consumeFocusEvent(false);
4233 mSecondWindow->consumeFocusEvent(true);
4234 mFakePolicy->waitForSetPointerCapture(false);
4235
4236 // Ensure that additional state changes from InputReader are not sent to the window.
4237 notifyPointerCaptureChanged(false);
4238 notifyPointerCaptureChanged(true);
4239 notifyPointerCaptureChanged(false);
4240 mWindow->assertNoEvents();
4241 mSecondWindow->assertNoEvents();
4242 mFakePolicy->assertSetPointerCaptureNotCalled();
4243}
4244
4245TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
4246 requestAndVerifyPointerCapture(mWindow, true);
4247
4248 // InputReader unexpectedly disables and enables pointer capture.
4249 notifyPointerCaptureChanged(false);
4250 notifyPointerCaptureChanged(true);
4251
4252 // Ensure that Pointer Capture is disabled.
Prabir Pradhan7d030382020-12-21 07:58:35 -08004253 mFakePolicy->waitForSetPointerCapture(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08004254 mWindow->consumeCaptureEvent(false);
4255 mWindow->assertNoEvents();
4256}
4257
Prabir Pradhan167e6d92021-02-04 16:18:17 -08004258TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
4259 requestAndVerifyPointerCapture(mWindow, true);
4260
4261 // The first window loses focus.
4262 setFocusedWindow(mSecondWindow);
4263 mFakePolicy->waitForSetPointerCapture(false);
4264 mWindow->consumeCaptureEvent(false);
4265
4266 // Request Pointer Capture from the second window before the notification from InputReader
4267 // arrives.
4268 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
4269 mFakePolicy->waitForSetPointerCapture(true);
4270
4271 // InputReader notifies Pointer Capture was disabled (because of the focus change).
4272 notifyPointerCaptureChanged(false);
4273
4274 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
4275 notifyPointerCaptureChanged(true);
4276
4277 mSecondWindow->consumeFocusEvent(true);
4278 mSecondWindow->consumeCaptureEvent(true);
4279}
4280
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004281class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
4282protected:
4283 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00004284
4285 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
4286 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
4287
4288 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
4289 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
4290
4291 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
4292 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
4293 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
4294 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
4295 MAXIMUM_OBSCURING_OPACITY);
4296
Bernardo Rufino6d52e542021-02-15 18:38:10 +00004297 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004298 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004299 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004300
4301 sp<FakeWindowHandle> mTouchWindow;
4302
4303 virtual void SetUp() override {
4304 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00004305 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004306 mDispatcher->setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode::BLOCK);
4307 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
4308 }
4309
4310 virtual void TearDown() override {
4311 InputDispatcherTest::TearDown();
4312 mTouchWindow.clear();
4313 }
4314
4315 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name,
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004316 os::TouchOcclusionMode mode, float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004317 sp<FakeWindowHandle> window = getWindow(uid, name);
4318 window->setFlags(InputWindowInfo::Flag::NOT_TOUCHABLE);
4319 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004320 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004321 return window;
4322 }
4323
4324 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
4325 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
4326 sp<FakeWindowHandle> window =
4327 new FakeWindowHandle(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
4328 // Generate an arbitrary PID based on the UID
4329 window->setOwnerInfo(1777 + (uid % 10000), uid);
4330 return window;
4331 }
4332
4333 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
4334 NotifyMotionArgs args =
4335 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4336 ADISPLAY_ID_DEFAULT, points);
4337 mDispatcher->notifyMotion(&args);
4338 }
4339};
4340
4341TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004342 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004343 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004344 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004345
4346 touch();
4347
4348 mTouchWindow->assertNoEvents();
4349}
4350
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00004351TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00004352 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
4353 const sp<FakeWindowHandle>& w =
4354 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
4355 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4356
4357 touch();
4358
4359 mTouchWindow->assertNoEvents();
4360}
4361
4362TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00004363 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
4364 const sp<FakeWindowHandle>& w =
4365 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
4366 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4367
4368 touch();
4369
4370 w->assertNoEvents();
4371}
4372
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004373TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004374 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
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, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004383 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004384 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004385 w->setFrame(Rect(0, 0, 50, 50));
4386 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004387
4388 touch({PointF{100, 100}});
4389
4390 mTouchWindow->consumeAnyMotionDown();
4391}
4392
4393TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004394 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00004395 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004396 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4397
4398 touch();
4399
4400 mTouchWindow->consumeAnyMotionDown();
4401}
4402
4403TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
4404 const sp<FakeWindowHandle>& w =
4405 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
4406 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004407
4408 touch();
4409
4410 mTouchWindow->consumeAnyMotionDown();
4411}
4412
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00004413TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
4414 const sp<FakeWindowHandle>& w =
4415 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
4416 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4417
4418 touch();
4419
4420 w->assertNoEvents();
4421}
4422
4423/**
4424 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
4425 * inside) while letting them pass-through. Note that even though touch passes through the occluding
4426 * window, the occluding window will still receive ACTION_OUTSIDE event.
4427 */
4428TEST_F(InputDispatcherUntrustedTouchesTest,
4429 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
4430 const sp<FakeWindowHandle>& w =
4431 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
4432 w->addFlags(InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH);
4433 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4434
4435 touch();
4436
4437 w->consumeMotionOutside();
4438}
4439
4440TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
4441 const sp<FakeWindowHandle>& w =
4442 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
4443 w->addFlags(InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH);
4444 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4445
4446 touch();
4447
4448 InputEvent* event = w->consume();
4449 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
4450 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
4451 EXPECT_EQ(0.0f, motionEvent.getRawPointerCoords(0)->getX());
4452 EXPECT_EQ(0.0f, motionEvent.getRawPointerCoords(0)->getY());
4453}
4454
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004455TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004456 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004457 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
4458 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004459 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4460
4461 touch();
4462
4463 mTouchWindow->consumeAnyMotionDown();
4464}
4465
4466TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
4467 const sp<FakeWindowHandle>& w =
4468 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
4469 MAXIMUM_OBSCURING_OPACITY);
4470 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004471
4472 touch();
4473
4474 mTouchWindow->consumeAnyMotionDown();
4475}
4476
4477TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004478 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004479 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
4480 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004481 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4482
4483 touch();
4484
4485 mTouchWindow->assertNoEvents();
4486}
4487
4488TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
4489 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
4490 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004491 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
4492 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004493 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004494 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
4495 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004496 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
4497
4498 touch();
4499
4500 mTouchWindow->assertNoEvents();
4501}
4502
4503TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
4504 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
4505 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004506 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
4507 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004508 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004509 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
4510 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004511 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
4512
4513 touch();
4514
4515 mTouchWindow->consumeAnyMotionDown();
4516}
4517
4518TEST_F(InputDispatcherUntrustedTouchesTest,
4519 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
4520 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004521 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
4522 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004523 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004524 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
4525 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004526 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
4527
4528 touch();
4529
4530 mTouchWindow->consumeAnyMotionDown();
4531}
4532
4533TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
4534 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004535 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
4536 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004537 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004538 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
4539 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004540 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004541
4542 touch();
4543
4544 mTouchWindow->assertNoEvents();
4545}
4546
Bernardo Rufino6d52e542021-02-15 18:38:10 +00004547TEST_F(InputDispatcherUntrustedTouchesTest,
4548 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
4549 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004550 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
4551 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00004552 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004553 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
4554 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00004555 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
4556
4557 touch();
4558
4559 mTouchWindow->assertNoEvents();
4560}
4561
4562TEST_F(InputDispatcherUntrustedTouchesTest,
4563 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
4564 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004565 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
4566 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00004567 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004568 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
4569 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00004570 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
4571
4572 touch();
4573
4574 mTouchWindow->consumeAnyMotionDown();
4575}
4576
4577TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
4578 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004579 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
4580 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00004581 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4582
4583 touch();
4584
4585 mTouchWindow->consumeAnyMotionDown();
4586}
4587
4588TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
4589 const sp<FakeWindowHandle>& w =
4590 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
4591 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4592
4593 touch();
4594
4595 mTouchWindow->consumeAnyMotionDown();
4596}
4597
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00004598TEST_F(InputDispatcherUntrustedTouchesTest,
4599 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
4600 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
4601 const sp<FakeWindowHandle>& w =
4602 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
4603 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4604
4605 touch();
4606
4607 mTouchWindow->assertNoEvents();
4608}
4609
4610TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
4611 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
4612 const sp<FakeWindowHandle>& w =
4613 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
4614 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4615
4616 touch();
4617
4618 mTouchWindow->consumeAnyMotionDown();
4619}
4620
4621TEST_F(InputDispatcherUntrustedTouchesTest,
4622 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
4623 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
4624 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004625 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
4626 OPACITY_ABOVE_THRESHOLD);
4627 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4628
4629 touch();
4630
4631 mTouchWindow->consumeAnyMotionDown();
4632}
4633
4634TEST_F(InputDispatcherUntrustedTouchesTest,
4635 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
4636 const sp<FakeWindowHandle>& w1 =
4637 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
4638 OPACITY_BELOW_THRESHOLD);
4639 const sp<FakeWindowHandle>& w2 =
4640 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
4641 OPACITY_BELOW_THRESHOLD);
4642 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
4643
4644 touch();
4645
4646 mTouchWindow->assertNoEvents();
4647}
4648
4649/**
4650 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
4651 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
4652 * (which alone would result in allowing touches) does not affect the blocking behavior.
4653 */
4654TEST_F(InputDispatcherUntrustedTouchesTest,
4655 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
4656 const sp<FakeWindowHandle>& wB =
4657 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
4658 OPACITY_BELOW_THRESHOLD);
4659 const sp<FakeWindowHandle>& wC =
4660 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
4661 OPACITY_BELOW_THRESHOLD);
4662 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
4663
4664 touch();
4665
4666 mTouchWindow->assertNoEvents();
4667}
4668
4669/**
4670 * This test is testing that a window from a different UID but with same application token doesn't
4671 * block the touch. Apps can share the application token for close UI collaboration for example.
4672 */
4673TEST_F(InputDispatcherUntrustedTouchesTest,
4674 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
4675 const sp<FakeWindowHandle>& w =
4676 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
4677 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00004678 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4679
4680 touch();
4681
4682 mTouchWindow->consumeAnyMotionDown();
4683}
4684
Garfield Tane84e6f92019-08-29 17:28:41 -07004685} // namespace android::inputdispatcher