blob: ca77d7ac0a819b1c41f830e7ce684db635772a5f [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
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070019#include <android-base/properties.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080020#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070021#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070022#include <binder/Binder.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080023#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100024#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080025#include <linux/input.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100026
Garfield Tan1c7bc862020-01-28 13:24:04 -080027#include <cinttypes>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070028#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080029#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080030#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080031
Garfield Tan1c7bc862020-01-28 13:24:04 -080032using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050033using android::gui::FocusRequest;
34using android::gui::TouchOcclusionMode;
35using android::gui::WindowInfo;
36using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080037using android::os::InputEventInjectionResult;
38using android::os::InputEventInjectionSync;
Michael Wright44753b12020-07-08 13:48:11 +010039using namespace android::flag_operators;
Garfield Tan1c7bc862020-01-28 13:24:04 -080040
Garfield Tane84e6f92019-08-29 17:28:41 -070041namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080042
43// An arbitrary time value.
44static const nsecs_t ARBITRARY_TIME = 1234;
45
46// An arbitrary device id.
47static const int32_t DEVICE_ID = 1;
48
Jeff Brownf086ddb2014-02-11 14:28:48 -080049// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000050static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
51static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080052
Michael Wrightd02c5b62014-02-10 15:10:22 -080053// An arbitrary injector pid / uid pair that has permission to inject events.
54static const int32_t INJECTOR_PID = 999;
55static const int32_t INJECTOR_UID = 1001;
56
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +000057// An arbitrary pid of the gesture monitor window
58static constexpr int32_t MONITOR_PID = 2001;
59
chaviwd1c23182019-12-20 18:44:56 -080060struct PointF {
61 float x;
62 float y;
63};
Michael Wrightd02c5b62014-02-10 15:10:22 -080064
Gang Wang342c9272020-01-13 13:15:04 -050065/**
66 * Return a DOWN key event with KEYCODE_A.
67 */
68static KeyEvent getTestKeyEvent() {
69 KeyEvent event;
70
Garfield Tanfbe732e2020-01-24 11:26:14 -080071 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
72 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
73 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050074 return event;
75}
76
Siarhei Vishniakouca205502021-07-16 21:31:58 +000077static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
78 ASSERT_EQ(expectedAction, receivedAction)
79 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
80 << MotionEvent::actionToString(receivedAction);
81}
82
Michael Wrightd02c5b62014-02-10 15:10:22 -080083// --- FakeInputDispatcherPolicy ---
84
85class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
86 InputDispatcherConfiguration mConfig;
87
88protected:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100089 virtual ~FakeInputDispatcherPolicy() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -080090
91public:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100092 FakeInputDispatcherPolicy() {}
Jackal Guof9696682018-10-05 12:23:23 +080093
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080094 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -070095 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
96 ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_KEY);
97 EXPECT_EQ(event.getDisplayId(), args.displayId);
98
99 const auto& keyEvent = static_cast<const KeyEvent&>(event);
100 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
101 EXPECT_EQ(keyEvent.getAction(), args.action);
102 });
Jackal Guof9696682018-10-05 12:23:23 +0800103 }
104
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700105 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
106 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
107 ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_MOTION);
108 EXPECT_EQ(event.getDisplayId(), args.displayId);
109
110 const auto& motionEvent = static_cast<const MotionEvent&>(event);
111 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
112 EXPECT_EQ(motionEvent.getAction(), args.action);
113 EXPECT_EQ(motionEvent.getX(0), point.x);
114 EXPECT_EQ(motionEvent.getY(0), point.y);
115 EXPECT_EQ(motionEvent.getRawX(0), point.x);
116 EXPECT_EQ(motionEvent.getRawY(0), point.y);
117 });
Jackal Guof9696682018-10-05 12:23:23 +0800118 }
119
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700120 void assertFilterInputEventWasNotCalled() {
121 std::scoped_lock lock(mLock);
122 ASSERT_EQ(nullptr, mFilteredEvent);
123 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800124
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800125 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700126 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800127 ASSERT_TRUE(mConfigurationChangedTime)
128 << "Timed out waiting for configuration changed call";
129 ASSERT_EQ(*mConfigurationChangedTime, when);
130 mConfigurationChangedTime = std::nullopt;
131 }
132
133 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700134 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800135 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800136 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800137 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
138 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
139 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
140 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
141 mLastNotifySwitch = std::nullopt;
142 }
143
chaviwfd6d3512019-03-25 13:23:49 -0700144 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700145 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800146 ASSERT_EQ(touchedToken, mOnPointerDownToken);
147 mOnPointerDownToken.clear();
148 }
149
150 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700151 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800152 ASSERT_TRUE(mOnPointerDownToken == nullptr)
153 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700154 }
155
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700156 // This function must be called soon after the expected ANR timer starts,
157 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500158 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700159 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500160 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
161 std::shared_ptr<InputApplicationHandle> application;
162 { // acquire lock
163 std::unique_lock lock(mLock);
164 android::base::ScopedLockAssertion assumeLocked(mLock);
165 ASSERT_NO_FATAL_FAILURE(
166 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
167 } // release lock
168 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700169 }
170
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000171 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
172 const sp<IBinder>& expectedConnectionToken) {
173 sp<IBinder> connectionToken = getUnresponsiveWindowToken(timeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500174 ASSERT_EQ(expectedConnectionToken, connectionToken);
175 }
176
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000177 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedConnectionToken) {
178 sp<IBinder> connectionToken = getResponsiveWindowToken();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500179 ASSERT_EQ(expectedConnectionToken, connectionToken);
180 }
181
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000182 void assertNotifyMonitorUnresponsiveWasCalled(std::chrono::nanoseconds timeout) {
183 int32_t pid = getUnresponsiveMonitorPid(timeout);
184 ASSERT_EQ(MONITOR_PID, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500185 }
186
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000187 void assertNotifyMonitorResponsiveWasCalled() {
188 int32_t pid = getResponsiveMonitorPid();
189 ASSERT_EQ(MONITOR_PID, pid);
190 }
191
192 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500193 std::unique_lock lock(mLock);
194 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000195 return getAnrTokenLockedInterruptible(timeout, mAnrWindowTokens, lock);
196 }
197
198 sp<IBinder> getResponsiveWindowToken() {
199 std::unique_lock lock(mLock);
200 android::base::ScopedLockAssertion assumeLocked(mLock);
201 return getAnrTokenLockedInterruptible(0s, mResponsiveWindowTokens, lock);
202 }
203
204 int32_t getUnresponsiveMonitorPid(std::chrono::nanoseconds timeout) {
205 std::unique_lock lock(mLock);
206 android::base::ScopedLockAssertion assumeLocked(mLock);
207 return getAnrTokenLockedInterruptible(timeout, mAnrMonitorPids, lock);
208 }
209
210 int32_t getResponsiveMonitorPid() {
211 std::unique_lock lock(mLock);
212 android::base::ScopedLockAssertion assumeLocked(mLock);
213 return getAnrTokenLockedInterruptible(0s, mResponsiveMonitorPids, lock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500214 }
215
216 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
217 // for a specific container to become non-empty. When the container is non-empty, return the
218 // first entry from the container and erase it.
219 template <class T>
220 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
221 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
222 const std::chrono::time_point start = std::chrono::steady_clock::now();
223 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700224
225 // If there is an ANR, Dispatcher won't be idle because there are still events
226 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
227 // before checking if ANR was called.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500228 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
229 // to provide it some time to act. 100ms seems reasonable.
230 mNotifyAnr.wait_for(lock, timeToWait,
231 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700232 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500233 if (storage.empty()) {
234 ADD_FAILURE() << "Did not receive the ANR callback";
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000235 return {};
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700236 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700237 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
238 // the dispatcher started counting before this function was called
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700239 if (std::chrono::abs(timeout - waited) > 100ms) {
240 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
241 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
242 << "ms, but waited "
243 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
244 << "ms instead";
245 }
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500246 T token = storage.front();
247 storage.pop();
248 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700249 }
250
251 void assertNotifyAnrWasNotCalled() {
252 std::scoped_lock lock(mLock);
253 ASSERT_TRUE(mAnrApplications.empty());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000254 ASSERT_TRUE(mAnrWindowTokens.empty());
255 ASSERT_TRUE(mAnrMonitorPids.empty());
256 ASSERT_TRUE(mResponsiveWindowTokens.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500257 << "ANR was not called, but please also consume the 'connection is responsive' "
258 "signal";
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000259 ASSERT_TRUE(mResponsiveMonitorPids.empty())
260 << "Monitor ANR was not called, but please also consume the 'monitor is responsive'"
261 " signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700262 }
263
Garfield Tan1c7bc862020-01-28 13:24:04 -0800264 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
265 mConfig.keyRepeatTimeout = timeout;
266 mConfig.keyRepeatDelay = delay;
267 }
268
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000269 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800270 std::unique_lock lock(mLock);
271 base::ScopedLockAssertion assumeLocked(mLock);
272
273 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
274 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000275 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800276 enabled;
277 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000278 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
279 << ") to be called.";
280 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800281 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000282 auto request = *mPointerCaptureRequest;
283 mPointerCaptureRequest.reset();
284 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800285 }
286
287 void assertSetPointerCaptureNotCalled() {
288 std::unique_lock lock(mLock);
289 base::ScopedLockAssertion assumeLocked(mLock);
290
291 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000292 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800293 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000294 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800295 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000296 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800297 }
298
arthurhungf452d0b2021-01-06 00:19:52 +0800299 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
300 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800301 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800302 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800303 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800304 }
305
Michael Wrightd02c5b62014-02-10 15:10:22 -0800306private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700307 std::mutex mLock;
308 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
309 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
310 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
311 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800312
Prabir Pradhan99987712020-11-10 18:43:05 -0800313 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000314
315 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800316
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700317 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700318 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000319 std::queue<sp<IBinder>> mAnrWindowTokens GUARDED_BY(mLock);
320 std::queue<sp<IBinder>> mResponsiveWindowTokens GUARDED_BY(mLock);
321 std::queue<int32_t> mAnrMonitorPids GUARDED_BY(mLock);
322 std::queue<int32_t> mResponsiveMonitorPids GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700323 std::condition_variable mNotifyAnr;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700324
arthurhungf452d0b2021-01-06 00:19:52 +0800325 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800326 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800327
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600328 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700329 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800330 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800331 }
332
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000333 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700334 std::scoped_lock lock(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000335 mAnrWindowTokens.push(connectionToken);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700336 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500337 }
338
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000339 void notifyMonitorUnresponsive(int32_t pid, const std::string&) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500340 std::scoped_lock lock(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000341 mAnrMonitorPids.push(pid);
342 mNotifyAnr.notify_all();
343 }
344
345 void notifyWindowResponsive(const sp<IBinder>& connectionToken) override {
346 std::scoped_lock lock(mLock);
347 mResponsiveWindowTokens.push(connectionToken);
348 mNotifyAnr.notify_all();
349 }
350
351 void notifyMonitorResponsive(int32_t pid) override {
352 std::scoped_lock lock(mLock);
353 mResponsiveMonitorPids.push(pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500354 mNotifyAnr.notify_all();
355 }
356
357 void notifyNoFocusedWindowAnr(
358 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
359 std::scoped_lock lock(mLock);
360 mAnrApplications.push(applicationHandle);
361 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800362 }
363
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600364 void notifyInputChannelBroken(const sp<IBinder>&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800365
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600366 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700367
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600368 void notifyUntrustedTouch(const std::string& obscuringPackage) override {}
Chris Yef59a2f42020-10-16 12:55:26 -0700369 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
370 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
371 const std::vector<float>& values) override {}
372
373 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
374 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000375
Chris Yefb552902021-02-03 17:18:37 -0800376 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
377
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600378 void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800379 *outConfig = mConfig;
380 }
381
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600382 bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700383 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800384 switch (inputEvent->getType()) {
385 case AINPUT_EVENT_TYPE_KEY: {
386 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800387 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800388 break;
389 }
390
391 case AINPUT_EVENT_TYPE_MOTION: {
392 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800393 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800394 break;
395 }
396 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800397 return true;
398 }
399
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600400 void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800401
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600402 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800403
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600404 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800405 return 0;
406 }
407
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600408 bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800409 return false;
410 }
411
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600412 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
413 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700414 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800415 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
416 * essentially a passthrough for notifySwitch.
417 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800418 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800419 }
420
Sean Stoutb4e0a592021-02-23 07:34:53 -0800421 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800422
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800423 bool checkInjectEventsPermissionNonReentrant(int32_t pid, int32_t uid) override {
424 return pid == INJECTOR_PID && uid == INJECTOR_UID;
425 }
Jackal Guof9696682018-10-05 12:23:23 +0800426
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600427 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700428 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700429 mOnPointerDownToken = newToken;
430 }
431
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000432 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800433 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000434 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800435 mPointerCaptureChangedCondition.notify_all();
436 }
437
arthurhungf452d0b2021-01-06 00:19:52 +0800438 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
439 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800440 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800441 mDropTargetWindowToken = token;
442 }
443
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700444 void assertFilterInputEventWasCalledInternal(
445 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700446 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800447 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700448 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800449 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800450 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800451};
452
Michael Wrightd02c5b62014-02-10 15:10:22 -0800453// --- InputDispatcherTest ---
454
455class InputDispatcherTest : public testing::Test {
456protected:
457 sp<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700458 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800459
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000460 void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800461 mFakePolicy = new FakeInputDispatcherPolicy();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700462 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800463 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000464 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700465 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800466 }
467
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000468 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700469 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800470 mFakePolicy.clear();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700471 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800472 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700473
474 /**
475 * Used for debugging when writing the test
476 */
477 void dumpDispatcherState() {
478 std::string dump;
479 mDispatcher->dump(dump);
480 std::stringstream ss(dump);
481 std::string to;
482
483 while (std::getline(ss, to, '\n')) {
484 ALOGE("%s", to.c_str());
485 }
486 }
Vishnu Nair958da932020-08-21 17:12:37 -0700487
chaviw3277faf2021-05-19 16:45:23 -0500488 void setFocusedWindow(const sp<WindowInfoHandle>& window,
489 const sp<WindowInfoHandle>& focusedWindow = nullptr) {
Vishnu Nair958da932020-08-21 17:12:37 -0700490 FocusRequest request;
491 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000492 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700493 if (focusedWindow) {
494 request.focusedToken = focusedWindow->getToken();
495 }
496 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
497 request.displayId = window->getInfo()->displayId;
498 mDispatcher->setFocusedWindow(request);
499 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800500};
501
Michael Wrightd02c5b62014-02-10 15:10:22 -0800502TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
503 KeyEvent event;
504
505 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800506 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
507 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600508 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
509 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800510 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700511 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800512 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800513 << "Should reject key events with undefined action.";
514
515 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800516 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
517 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600518 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800519 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700520 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800521 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800522 << "Should reject key events with ACTION_MULTIPLE.";
523}
524
525TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
526 MotionEvent event;
527 PointerProperties pointerProperties[MAX_POINTERS + 1];
528 PointerCoords pointerCoords[MAX_POINTERS + 1];
529 for (int i = 0; i <= MAX_POINTERS; i++) {
530 pointerProperties[i].clear();
531 pointerProperties[i].id = i;
532 pointerCoords[i].clear();
533 }
534
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800535 // Some constants commonly used below
536 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
537 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
538 constexpr int32_t metaState = AMETA_NONE;
539 constexpr MotionClassification classification = MotionClassification::NONE;
540
chaviw9eaa22c2020-07-01 16:21:27 -0700541 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800542 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800543 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700544 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
545 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700546 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
547 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700548 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800549 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700550 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800551 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800552 << "Should reject motion events with undefined action.";
553
554 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800555 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700556 AMOTION_EVENT_ACTION_POINTER_DOWN |
557 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700558 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
559 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700560 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500561 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800562 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700563 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800564 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800565 << "Should reject motion events with pointer down index too large.";
566
Garfield Tanfbe732e2020-01-24 11:26:14 -0800567 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700568 AMOTION_EVENT_ACTION_POINTER_DOWN |
569 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700570 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
571 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700572 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500573 /*pointerCount*/ 1, 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 pointer down index too small.";
578
579 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800580 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700581 AMOTION_EVENT_ACTION_POINTER_UP |
582 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700583 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
584 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700585 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500586 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800587 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700588 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800589 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800590 << "Should reject motion events with pointer up index too large.";
591
Garfield Tanfbe732e2020-01-24 11:26:14 -0800592 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700593 AMOTION_EVENT_ACTION_POINTER_UP |
594 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700595 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
596 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700597 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500598 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800599 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700600 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800601 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800602 << "Should reject motion events with pointer up index too small.";
603
604 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800605 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
606 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700607 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700608 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
609 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700610 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800611 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700612 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800613 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800614 << "Should reject motion events with 0 pointers.";
615
Garfield Tanfbe732e2020-01-24 11:26:14 -0800616 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
617 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700618 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700619 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
620 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700621 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800622 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700623 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800624 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800625 << "Should reject motion events with more than MAX_POINTERS pointers.";
626
627 // Rejects motion events with invalid pointer ids.
628 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800629 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
630 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700631 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700632 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
633 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700634 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800635 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700636 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800637 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800638 << "Should reject motion events with pointer ids less than 0.";
639
640 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800641 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
642 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700643 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700644 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
645 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700646 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800647 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700648 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800649 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800650 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
651
652 // Rejects motion events with duplicate pointer ids.
653 pointerProperties[0].id = 1;
654 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800655 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
656 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700657 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700658 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
659 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700660 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800661 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700662 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800663 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800664 << "Should reject motion events with duplicate pointer ids.";
665}
666
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800667/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
668
669TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
670 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800671 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800672 mDispatcher->notifyConfigurationChanged(&args);
673 ASSERT_TRUE(mDispatcher->waitForIdle());
674
675 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
676}
677
678TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800679 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
680 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800681 mDispatcher->notifySwitch(&args);
682
683 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
684 args.policyFlags |= POLICY_FLAG_TRUSTED;
685 mFakePolicy->assertNotifySwitchWasCalled(args);
686}
687
Arthur Hungb92218b2018-08-14 12:00:21 +0800688// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700689static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700690// Default input dispatching timeout if there is no focused application or paused window
691// from which to determine an appropriate dispatching timeout.
692static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
693 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
694 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800695
696class FakeApplicationHandle : public InputApplicationHandle {
697public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700698 FakeApplicationHandle() {
699 mInfo.name = "Fake Application";
700 mInfo.token = new BBinder();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500701 mInfo.dispatchingTimeoutMillis =
702 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700703 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800704 virtual ~FakeApplicationHandle() {}
705
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000706 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700707
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500708 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
709 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700710 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800711};
712
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800713class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800714public:
Garfield Tan15601662020-09-22 15:32:38 -0700715 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800716 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700717 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800718 }
719
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800720 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700721 InputEvent* event;
722 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
723 if (!consumeSeq) {
724 return nullptr;
725 }
726 finishEvent(*consumeSeq);
727 return event;
728 }
729
730 /**
731 * Receive an event without acknowledging it.
732 * Return the sequence number that could later be used to send finished signal.
733 */
734 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800735 uint32_t consumeSeq;
736 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800737
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800738 std::chrono::time_point start = std::chrono::steady_clock::now();
739 status_t status = WOULD_BLOCK;
740 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800741 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800742 &event);
743 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
744 if (elapsed > 100ms) {
745 break;
746 }
747 }
748
749 if (status == WOULD_BLOCK) {
750 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700751 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800752 }
753
754 if (status != OK) {
755 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700756 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800757 }
758 if (event == nullptr) {
759 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700760 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800761 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700762 if (outEvent != nullptr) {
763 *outEvent = event;
764 }
765 return consumeSeq;
766 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800767
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700768 /**
769 * To be used together with "receiveEvent" to complete the consumption of an event.
770 */
771 void finishEvent(uint32_t consumeSeq) {
772 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
773 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800774 }
775
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000776 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
777 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
778 ASSERT_EQ(OK, status);
779 }
780
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000781 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
782 std::optional<int32_t> expectedDisplayId,
783 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800784 InputEvent* event = consume();
785
786 ASSERT_NE(nullptr, event) << mName.c_str()
787 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800788 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700789 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800790 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800791
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000792 if (expectedDisplayId.has_value()) {
793 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
794 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800795
Tiger Huang8664f8c2018-10-11 19:14:35 +0800796 switch (expectedEventType) {
797 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800798 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
799 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000800 if (expectedFlags.has_value()) {
801 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
802 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800803 break;
804 }
805 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800806 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000807 assertMotionAction(expectedAction, motionEvent.getAction());
808
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000809 if (expectedFlags.has_value()) {
810 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
811 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800812 break;
813 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100814 case AINPUT_EVENT_TYPE_FOCUS: {
815 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
816 }
Prabir Pradhan99987712020-11-10 18:43:05 -0800817 case AINPUT_EVENT_TYPE_CAPTURE: {
818 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
819 }
arthurhungb89ccb02020-12-30 16:19:01 +0800820 case AINPUT_EVENT_TYPE_DRAG: {
821 FAIL() << "Use 'consumeDragEvent' for DRAG events";
822 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800823 default: {
824 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
825 }
826 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800827 }
828
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100829 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
830 InputEvent* event = consume();
831 ASSERT_NE(nullptr, event) << mName.c_str()
832 << ": consumer should have returned non-NULL event.";
833 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
834 << "Got " << inputEventTypeToString(event->getType())
835 << " event instead of FOCUS event";
836
837 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
838 << mName.c_str() << ": event displayId should always be NONE.";
839
840 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
841 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
842 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
843 }
844
Prabir Pradhan99987712020-11-10 18:43:05 -0800845 void consumeCaptureEvent(bool hasCapture) {
846 const InputEvent* event = consume();
847 ASSERT_NE(nullptr, event) << mName.c_str()
848 << ": consumer should have returned non-NULL event.";
849 ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType())
850 << "Got " << inputEventTypeToString(event->getType())
851 << " event instead of CAPTURE event";
852
853 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
854 << mName.c_str() << ": event displayId should always be NONE.";
855
856 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
857 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
858 }
859
arthurhungb89ccb02020-12-30 16:19:01 +0800860 void consumeDragEvent(bool isExiting, float x, float y) {
861 const InputEvent* event = consume();
862 ASSERT_NE(nullptr, event) << mName.c_str()
863 << ": consumer should have returned non-NULL event.";
864 ASSERT_EQ(AINPUT_EVENT_TYPE_DRAG, event->getType())
865 << "Got " << inputEventTypeToString(event->getType())
866 << " event instead of DRAG event";
867
868 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
869 << mName.c_str() << ": event displayId should always be NONE.";
870
871 const auto& dragEvent = static_cast<const DragEvent&>(*event);
872 EXPECT_EQ(isExiting, dragEvent.isExiting());
873 EXPECT_EQ(x, dragEvent.getX());
874 EXPECT_EQ(y, dragEvent.getY());
875 }
876
chaviwd1c23182019-12-20 18:44:56 -0800877 void assertNoEvents() {
878 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700879 if (event == nullptr) {
880 return;
881 }
882 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
883 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
884 ADD_FAILURE() << "Received key event "
885 << KeyEvent::actionToString(keyEvent.getAction());
886 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
887 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
888 ADD_FAILURE() << "Received motion event "
889 << MotionEvent::actionToString(motionEvent.getAction());
890 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
891 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
892 ADD_FAILURE() << "Received focus event, hasFocus = "
893 << (focusEvent.getHasFocus() ? "true" : "false");
Prabir Pradhan99987712020-11-10 18:43:05 -0800894 } else if (event->getType() == AINPUT_EVENT_TYPE_CAPTURE) {
895 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
896 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
897 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700898 }
899 FAIL() << mName.c_str()
900 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800901 }
902
903 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
904
905protected:
906 std::unique_ptr<InputConsumer> mConsumer;
907 PreallocatedInputEventFactory mEventFactory;
908
909 std::string mName;
910};
911
chaviw3277faf2021-05-19 16:45:23 -0500912class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -0800913public:
914 static const int32_t WIDTH = 600;
915 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800916
Chris Yea209fde2020-07-22 13:54:51 -0700917 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700918 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500919 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -0800920 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500921 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -0700922 base::Result<std::unique_ptr<InputChannel>> channel =
923 dispatcher->createInputChannel(name);
924 token = (*channel)->getConnectionToken();
925 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -0800926 }
927
928 inputApplicationHandle->updateInfo();
929 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
930
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500931 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700932 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800933 mInfo.name = name;
chaviw3277faf2021-05-19 16:45:23 -0500934 mInfo.type = WindowInfo::Type::APPLICATION;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500935 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000936 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -0800937 mInfo.frameLeft = 0;
938 mInfo.frameTop = 0;
939 mInfo.frameRight = WIDTH;
940 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -0700941 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -0800942 mInfo.globalScaleFactor = 1.0;
943 mInfo.touchableRegion.clear();
944 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
945 mInfo.visible = true;
Vishnu Nair47074b82020-08-14 11:54:47 -0700946 mInfo.focusable = false;
chaviwd1c23182019-12-20 18:44:56 -0800947 mInfo.hasWallpaper = false;
948 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800949 mInfo.ownerPid = INJECTOR_PID;
950 mInfo.ownerUid = INJECTOR_UID;
chaviwd1c23182019-12-20 18:44:56 -0800951 mInfo.displayId = displayId;
952 }
953
Arthur Hungabbb9d82021-09-01 14:52:30 +0000954 sp<FakeWindowHandle> clone(
955 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700956 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId) {
Arthur Hungabbb9d82021-09-01 14:52:30 +0000957 sp<FakeWindowHandle> handle =
958 new FakeWindowHandle(inputApplicationHandle, dispatcher, mInfo.name + "(Mirror)",
959 displayId, mInfo.token);
960 return handle;
961 }
962
Vishnu Nair47074b82020-08-14 11:54:47 -0700963 void setFocusable(bool focusable) { mInfo.focusable = focusable; }
chaviwd1c23182019-12-20 18:44:56 -0800964
Vishnu Nair958da932020-08-21 17:12:37 -0700965 void setVisible(bool visible) { mInfo.visible = visible; }
966
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700967 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500968 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700969 }
970
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700971 void setPaused(bool paused) { mInfo.paused = paused; }
972
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000973 void setAlpha(float alpha) { mInfo.alpha = alpha; }
974
chaviw3277faf2021-05-19 16:45:23 -0500975 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000976
Bernardo Rufino7393d172021-02-26 13:56:11 +0000977 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
978
chaviwd1c23182019-12-20 18:44:56 -0800979 void setFrame(const Rect& frame) {
980 mInfo.frameLeft = frame.left;
981 mInfo.frameTop = frame.top;
982 mInfo.frameRight = frame.right;
983 mInfo.frameBottom = frame.bottom;
arthurhungb89ccb02020-12-30 16:19:01 +0800984 mInfo.transform.set(-frame.left, -frame.top);
chaviwd1c23182019-12-20 18:44:56 -0800985 mInfo.touchableRegion.clear();
986 mInfo.addTouchableRegion(frame);
987 }
988
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000989 void setType(WindowInfo::Type type) { mInfo.type = type; }
990
991 void setHasWallpaper(bool hasWallpaper) { mInfo.hasWallpaper = hasWallpaper; }
992
chaviw3277faf2021-05-19 16:45:23 -0500993 void addFlags(Flags<WindowInfo::Flag> flags) { mInfo.flags |= flags; }
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +0000994
chaviw3277faf2021-05-19 16:45:23 -0500995 void setFlags(Flags<WindowInfo::Flag> flags) { mInfo.flags = flags; }
chaviwd1c23182019-12-20 18:44:56 -0800996
chaviw3277faf2021-05-19 16:45:23 -0500997 void setInputFeatures(WindowInfo::Feature features) { mInfo.inputFeatures = features; }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500998
chaviw9eaa22c2020-07-01 16:21:27 -0700999 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1000 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1001 }
1002
1003 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001004
yunho.shinf4a80b82020-11-16 21:13:57 +09001005 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1006
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001007 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1008 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1009 expectedFlags);
1010 }
1011
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001012 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1013 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
1014 }
1015
Svet Ganov5d3bc372020-01-26 23:11:07 -08001016 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001017 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -08001018 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
1019 expectedFlags);
1020 }
1021
1022 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001023 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -08001024 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
1025 expectedFlags);
1026 }
1027
1028 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001029 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001030 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1031 }
1032
1033 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1034 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001035 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
1036 expectedFlags);
1037 }
1038
Svet Ganov5d3bc372020-01-26 23:11:07 -08001039 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001040 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1041 int32_t expectedFlags = 0) {
1042 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1043 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001044 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1045 }
1046
1047 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001048 int32_t expectedFlags = 0) {
1049 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1050 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001051 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1052 }
1053
1054 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001055 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +00001056 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
1057 expectedFlags);
1058 }
1059
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001060 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1061 int32_t expectedFlags = 0) {
1062 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
1063 expectedFlags);
1064 }
1065
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001066 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1067 ASSERT_NE(mInputReceiver, nullptr)
1068 << "Cannot consume events from a window with no receiver";
1069 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1070 }
1071
Prabir Pradhan99987712020-11-10 18:43:05 -08001072 void consumeCaptureEvent(bool hasCapture) {
1073 ASSERT_NE(mInputReceiver, nullptr)
1074 << "Cannot consume events from a window with no receiver";
1075 mInputReceiver->consumeCaptureEvent(hasCapture);
1076 }
1077
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001078 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
1079 std::optional<int32_t> expectedDisplayId,
1080 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001081 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1082 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1083 expectedFlags);
1084 }
1085
arthurhungb89ccb02020-12-30 16:19:01 +08001086 void consumeDragEvent(bool isExiting, float x, float y) {
1087 mInputReceiver->consumeDragEvent(isExiting, x, y);
1088 }
1089
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001090 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001091 if (mInputReceiver == nullptr) {
1092 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1093 return std::nullopt;
1094 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001095 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001096 }
1097
1098 void finishEvent(uint32_t sequenceNum) {
1099 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1100 mInputReceiver->finishEvent(sequenceNum);
1101 }
1102
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001103 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1104 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1105 mInputReceiver->sendTimeline(inputEventId, timeline);
1106 }
1107
chaviwaf87b3e2019-10-01 16:59:28 -07001108 InputEvent* consume() {
1109 if (mInputReceiver == nullptr) {
1110 return nullptr;
1111 }
1112 return mInputReceiver->consume();
1113 }
1114
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001115 MotionEvent* consumeMotion() {
1116 InputEvent* event = consume();
1117 if (event == nullptr) {
1118 ADD_FAILURE() << "Consume failed : no event";
1119 return nullptr;
1120 }
1121 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
1122 ADD_FAILURE() << "Instead of motion event, got "
1123 << inputEventTypeToString(event->getType());
1124 return nullptr;
1125 }
1126 return static_cast<MotionEvent*>(event);
1127 }
1128
Arthur Hungb92218b2018-08-14 12:00:21 +08001129 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001130 if (mInputReceiver == nullptr &&
chaviw3277faf2021-05-19 16:45:23 -05001131 mInfo.inputFeatures.test(WindowInfo::Feature::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001132 return; // Can't receive events if the window does not have input channel
1133 }
1134 ASSERT_NE(nullptr, mInputReceiver)
1135 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001136 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001137 }
1138
chaviwaf87b3e2019-10-01 16:59:28 -07001139 sp<IBinder> getToken() { return mInfo.token; }
1140
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001141 const std::string& getName() { return mName; }
1142
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001143 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1144 mInfo.ownerPid = ownerPid;
1145 mInfo.ownerUid = ownerUid;
1146 }
1147
chaviwd1c23182019-12-20 18:44:56 -08001148private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001149 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001150 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001151 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001152};
1153
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001154std::atomic<int32_t> FakeWindowHandle::sId{1};
1155
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001156static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001157 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001158 int32_t displayId = ADISPLAY_ID_NONE,
1159 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001160 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
1161 bool allowKeyRepeat = true) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001162 KeyEvent event;
1163 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1164
1165 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001166 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001167 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
1168 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001169
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001170 int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
1171 if (!allowKeyRepeat) {
1172 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1173 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001174 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001175 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001176 injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001177}
1178
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001179static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001180 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001181 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
1182}
1183
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001184// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1185// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1186// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001187static InputEventInjectionResult injectKeyDownNoRepeat(
1188 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001189 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId,
1190 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
1191 /* allowKeyRepeat */ false);
1192}
1193
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001194static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001195 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001196 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
1197}
1198
Garfield Tandf26e862020-07-01 20:18:19 -07001199class PointerBuilder {
1200public:
1201 PointerBuilder(int32_t id, int32_t toolType) {
1202 mProperties.clear();
1203 mProperties.id = id;
1204 mProperties.toolType = toolType;
1205 mCoords.clear();
1206 }
1207
1208 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1209
1210 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1211
1212 PointerBuilder& axis(int32_t axis, float value) {
1213 mCoords.setAxisValue(axis, value);
1214 return *this;
1215 }
1216
1217 PointerProperties buildProperties() const { return mProperties; }
1218
1219 PointerCoords buildCoords() const { return mCoords; }
1220
1221private:
1222 PointerProperties mProperties;
1223 PointerCoords mCoords;
1224};
1225
1226class MotionEventBuilder {
1227public:
1228 MotionEventBuilder(int32_t action, int32_t source) {
1229 mAction = action;
1230 mSource = source;
1231 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1232 }
1233
1234 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1235 mEventTime = eventTime;
1236 return *this;
1237 }
1238
1239 MotionEventBuilder& displayId(int32_t displayId) {
1240 mDisplayId = displayId;
1241 return *this;
1242 }
1243
1244 MotionEventBuilder& actionButton(int32_t actionButton) {
1245 mActionButton = actionButton;
1246 return *this;
1247 }
1248
arthurhung6d4bed92021-03-17 11:59:33 +08001249 MotionEventBuilder& buttonState(int32_t buttonState) {
1250 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001251 return *this;
1252 }
1253
1254 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1255 mRawXCursorPosition = rawXCursorPosition;
1256 return *this;
1257 }
1258
1259 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1260 mRawYCursorPosition = rawYCursorPosition;
1261 return *this;
1262 }
1263
1264 MotionEventBuilder& pointer(PointerBuilder pointer) {
1265 mPointers.push_back(pointer);
1266 return *this;
1267 }
1268
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001269 MotionEventBuilder& addFlag(uint32_t flags) {
1270 mFlags |= flags;
1271 return *this;
1272 }
1273
Garfield Tandf26e862020-07-01 20:18:19 -07001274 MotionEvent build() {
1275 std::vector<PointerProperties> pointerProperties;
1276 std::vector<PointerCoords> pointerCoords;
1277 for (const PointerBuilder& pointer : mPointers) {
1278 pointerProperties.push_back(pointer.buildProperties());
1279 pointerCoords.push_back(pointer.buildCoords());
1280 }
1281
1282 // Set mouse cursor position for the most common cases to avoid boilerplate.
1283 if (mSource == AINPUT_SOURCE_MOUSE &&
1284 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1285 mPointers.size() == 1) {
1286 mRawXCursorPosition = pointerCoords[0].getX();
1287 mRawYCursorPosition = pointerCoords[0].getY();
1288 }
1289
1290 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001291 ui::Transform identityTransform;
Garfield Tandf26e862020-07-01 20:18:19 -07001292 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001293 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001294 mButtonState, MotionClassification::NONE, identityTransform,
1295 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07001296 mRawYCursorPosition, identityTransform, mEventTime, mEventTime,
1297 mPointers.size(), pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001298
1299 return event;
1300 }
1301
1302private:
1303 int32_t mAction;
1304 int32_t mSource;
1305 nsecs_t mEventTime;
1306 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1307 int32_t mActionButton{0};
1308 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001309 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001310 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1311 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1312
1313 std::vector<PointerBuilder> mPointers;
1314};
1315
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001316static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001317 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001318 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001319 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT) {
Garfield Tandf26e862020-07-01 20:18:19 -07001320 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
1321 injectionTimeout,
1322 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
1323}
1324
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001325static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001326 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
1327 int32_t displayId, const PointF& position,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001328 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001329 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1330 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001331 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001332 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Garfield Tandf26e862020-07-01 20:18:19 -07001333 MotionEvent event = MotionEventBuilder(action, source)
1334 .displayId(displayId)
1335 .eventTime(eventTime)
1336 .rawXCursorPosition(cursorPosition.x)
1337 .rawYCursorPosition(cursorPosition.y)
1338 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1339 .x(position.x)
1340 .y(position.y))
1341 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001342
1343 // Inject event until dispatch out.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001344 return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode);
Arthur Hungb92218b2018-08-14 12:00:21 +08001345}
1346
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001347static InputEventInjectionResult injectMotionDown(
1348 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1349 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001350 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001351}
1352
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001353static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001354 int32_t source, int32_t displayId,
1355 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001356 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001357}
1358
Jackal Guof9696682018-10-05 12:23:23 +08001359static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1360 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1361 // Define a valid key event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001362 NotifyKeyArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1363 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1364 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001365
1366 return args;
1367}
1368
chaviwd1c23182019-12-20 18:44:56 -08001369static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1370 const std::vector<PointF>& points) {
1371 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001372 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1373 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1374 }
1375
chaviwd1c23182019-12-20 18:44:56 -08001376 PointerProperties pointerProperties[pointerCount];
1377 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001378
chaviwd1c23182019-12-20 18:44:56 -08001379 for (size_t i = 0; i < pointerCount; i++) {
1380 pointerProperties[i].clear();
1381 pointerProperties[i].id = i;
1382 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001383
chaviwd1c23182019-12-20 18:44:56 -08001384 pointerCoords[i].clear();
1385 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1386 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1387 }
Jackal Guof9696682018-10-05 12:23:23 +08001388
1389 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1390 // Define a valid motion event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001391 NotifyMotionArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001392 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1393 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001394 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1395 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001396 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1397 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001398
1399 return args;
1400}
1401
chaviwd1c23182019-12-20 18:44:56 -08001402static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1403 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1404}
1405
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001406static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1407 const PointerCaptureRequest& request) {
1408 return NotifyPointerCaptureChangedArgs(/* id */ 0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001409}
1410
Arthur Hungb92218b2018-08-14 12:00:21 +08001411TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001412 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001413 sp<FakeWindowHandle> window =
1414 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001415
Arthur Hung72d8dc32020-03-28 00:48:39 +00001416 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1418 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1419 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001420
1421 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001422 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001423}
1424
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001425/**
1426 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1427 * To ensure that window receives only events that were directly inside of it, add
1428 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1429 * when finding touched windows.
1430 * This test serves as a sanity check for the next test, where setInputWindows is
1431 * called twice.
1432 */
1433TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001434 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001435 sp<FakeWindowHandle> window =
1436 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1437 window->setFrame(Rect(0, 0, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05001438 window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001439
1440 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001442 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1443 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001444 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001445
1446 // Window should receive motion event.
1447 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1448}
1449
1450/**
1451 * Calling setInputWindows twice, with the same info, should not cause any issues.
1452 * To ensure that window receives only events that were directly inside of it, add
1453 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1454 * when finding touched windows.
1455 */
1456TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001457 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001458 sp<FakeWindowHandle> window =
1459 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1460 window->setFrame(Rect(0, 0, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05001461 window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001462
1463 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1464 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001466 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1467 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001468 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001469
1470 // Window should receive motion event.
1471 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1472}
1473
Arthur Hungb92218b2018-08-14 12:00:21 +08001474// The foreground window should receive the first touch down event.
1475TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001476 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001477 sp<FakeWindowHandle> windowTop =
1478 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1479 sp<FakeWindowHandle> windowSecond =
1480 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001481
Arthur Hung72d8dc32020-03-28 00:48:39 +00001482 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001483 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1484 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1485 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001486
1487 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001488 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001489 windowSecond->assertNoEvents();
1490}
1491
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001492/**
1493 * Two windows: A top window, and a wallpaper behind the window.
1494 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1495 * gets ACTION_CANCEL.
1496 * 1. foregroundWindow <-- has wallpaper (hasWallpaper=true)
1497 * 2. wallpaperWindow <-- is wallpaper (type=InputWindowInfo::Type::WALLPAPER)
1498 */
1499TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1500 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1501 sp<FakeWindowHandle> foregroundWindow =
1502 new FakeWindowHandle(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1503 foregroundWindow->setHasWallpaper(true);
1504 sp<FakeWindowHandle> wallpaperWindow =
1505 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
1506 wallpaperWindow->setType(WindowInfo::Type::WALLPAPER);
1507 constexpr int expectedWallpaperFlags =
1508 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1509
1510 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1511 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1512 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1513 {100, 200}))
1514 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1515
1516 // Both foreground window and its wallpaper should receive the touch down
1517 foregroundWindow->consumeMotionDown();
1518 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1519
1520 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1521 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1522 ADISPLAY_ID_DEFAULT, {110, 200}))
1523 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1524
1525 foregroundWindow->consumeMotionMove();
1526 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1527
1528 // Now the foreground window goes away, but the wallpaper stays
1529 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1530 foregroundWindow->consumeMotionCancel();
1531 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1532 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1533}
1534
1535/**
1536 * A single window that receives touch (on top), and a wallpaper window underneath it.
1537 * The top window gets a multitouch gesture.
1538 * Ensure that wallpaper gets the same gesture.
1539 */
1540TEST_F(InputDispatcherTest, WallpaperWindow_ReceivesMultiTouch) {
1541 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1542 sp<FakeWindowHandle> window =
1543 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1544 window->setHasWallpaper(true);
1545
1546 sp<FakeWindowHandle> wallpaperWindow =
1547 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
1548 wallpaperWindow->setType(WindowInfo::Type::WALLPAPER);
1549 constexpr int expectedWallpaperFlags =
1550 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1551
1552 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, wallpaperWindow}}});
1553
1554 // Touch down on top window
1555 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1556 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1557 {100, 100}))
1558 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1559
1560 // Both top window and its wallpaper should receive the touch down
1561 window->consumeMotionDown();
1562 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1563
1564 // Second finger down on the top window
1565 const MotionEvent secondFingerDownEvent =
1566 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
1567 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1568 AINPUT_SOURCE_TOUCHSCREEN)
1569 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1570 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1571 .x(100)
1572 .y(100))
1573 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1574 .x(150)
1575 .y(150))
1576 .build();
1577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1578 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1579 InputEventInjectionSync::WAIT_FOR_RESULT))
1580 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1581
1582 window->consumeMotionPointerDown(1 /* pointerIndex */);
1583 wallpaperWindow->consumeMotionPointerDown(1 /* pointerIndex */, ADISPLAY_ID_DEFAULT,
1584 expectedWallpaperFlags);
1585 window->assertNoEvents();
1586 wallpaperWindow->assertNoEvents();
1587}
1588
1589/**
1590 * Two windows: a window on the left and window on the right.
1591 * A third window, wallpaper, is behind both windows, and spans both top windows.
1592 * The first touch down goes to the left window. A second pointer touches down on the right window.
1593 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1594 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1595 * ACTION_POINTER_DOWN(1).
1596 */
1597TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1598 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1599 sp<FakeWindowHandle> leftWindow =
1600 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1601 leftWindow->setFrame(Rect(0, 0, 200, 200));
1602 leftWindow->setFlags(WindowInfo::Flag::SPLIT_TOUCH | WindowInfo::Flag::NOT_TOUCH_MODAL);
1603 leftWindow->setHasWallpaper(true);
1604
1605 sp<FakeWindowHandle> rightWindow =
1606 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1607 rightWindow->setFrame(Rect(200, 0, 400, 200));
1608 rightWindow->setFlags(WindowInfo::Flag::SPLIT_TOUCH | WindowInfo::Flag::NOT_TOUCH_MODAL);
1609 rightWindow->setHasWallpaper(true);
1610
1611 sp<FakeWindowHandle> wallpaperWindow =
1612 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
1613 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
1614 wallpaperWindow->setType(WindowInfo::Type::WALLPAPER);
1615 constexpr int expectedWallpaperFlags =
1616 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1617
1618 mDispatcher->setInputWindows(
1619 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1620
1621 // Touch down on left window
1622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1623 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1624 {100, 100}))
1625 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1626
1627 // Both foreground window and its wallpaper should receive the touch down
1628 leftWindow->consumeMotionDown();
1629 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1630
1631 // Second finger down on the right window
1632 const MotionEvent secondFingerDownEvent =
1633 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
1634 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1635 AINPUT_SOURCE_TOUCHSCREEN)
1636 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1637 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1638 .x(100)
1639 .y(100))
1640 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1641 .x(300)
1642 .y(100))
1643 .build();
1644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1645 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1646 InputEventInjectionSync::WAIT_FOR_RESULT))
1647 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1648
1649 leftWindow->consumeMotionMove();
1650 // Since the touch is split, right window gets ACTION_DOWN
1651 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1652 wallpaperWindow->consumeMotionPointerDown(1 /* pointerIndex */, ADISPLAY_ID_DEFAULT,
1653 expectedWallpaperFlags);
1654
1655 // Now, leftWindow, which received the first finger, disappears.
1656 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
1657 leftWindow->consumeMotionCancel();
1658 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1659 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1660
1661 // The pointer that's still down on the right window moves, and goes to the right window only.
1662 // As far as the dispatcher's concerned though, both pointers are still present.
1663 const MotionEvent secondFingerMoveEvent =
1664 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1665 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1666 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1667 .x(100)
1668 .y(100))
1669 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1670 .x(310)
1671 .y(110))
1672 .build();
1673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1674 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
1675 InputEventInjectionSync::WAIT_FOR_RESULT));
1676 rightWindow->consumeMotionMove();
1677
1678 leftWindow->assertNoEvents();
1679 rightWindow->assertNoEvents();
1680 wallpaperWindow->assertNoEvents();
1681}
1682
Garfield Tandf26e862020-07-01 20:18:19 -07001683TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001684 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001685 sp<FakeWindowHandle> windowLeft =
1686 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1687 windowLeft->setFrame(Rect(0, 0, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05001688 windowLeft->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001689 sp<FakeWindowHandle> windowRight =
1690 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1691 windowRight->setFrame(Rect(600, 0, 1200, 800));
chaviw3277faf2021-05-19 16:45:23 -05001692 windowRight->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001693
1694 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1695
1696 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
1697
1698 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001700 injectMotionEvent(mDispatcher,
1701 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1702 AINPUT_SOURCE_MOUSE)
1703 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1704 .x(900)
1705 .y(400))
1706 .build()));
1707 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1708 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1709 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1710 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1711
1712 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001713 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001714 injectMotionEvent(mDispatcher,
1715 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1716 AINPUT_SOURCE_MOUSE)
1717 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1718 .x(300)
1719 .y(400))
1720 .build()));
1721 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1722 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1723 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1724 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1725 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1726 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1727
1728 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001729 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001730 injectMotionEvent(mDispatcher,
1731 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1732 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1733 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1734 .x(300)
1735 .y(400))
1736 .build()));
1737 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1738
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001740 injectMotionEvent(mDispatcher,
1741 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1742 AINPUT_SOURCE_MOUSE)
1743 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1744 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1745 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1746 .x(300)
1747 .y(400))
1748 .build()));
1749 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1750 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1751
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001753 injectMotionEvent(mDispatcher,
1754 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1755 AINPUT_SOURCE_MOUSE)
1756 .buttonState(0)
1757 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1758 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1759 .x(300)
1760 .y(400))
1761 .build()));
1762 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1763 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1764
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001766 injectMotionEvent(mDispatcher,
1767 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1768 .buttonState(0)
1769 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1770 .x(300)
1771 .y(400))
1772 .build()));
1773 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1774
1775 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001777 injectMotionEvent(mDispatcher,
1778 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1779 AINPUT_SOURCE_MOUSE)
1780 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1781 .x(900)
1782 .y(400))
1783 .build()));
1784 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1785 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1786 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1787 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1788 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1789 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1790}
1791
1792// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
1793// directly in this test.
1794TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001796 sp<FakeWindowHandle> window =
1797 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1798 window->setFrame(Rect(0, 0, 1200, 800));
chaviw3277faf2021-05-19 16:45:23 -05001799 window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001800
1801 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1802
1803 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1804
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001805 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001806 injectMotionEvent(mDispatcher,
1807 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
1808 AINPUT_SOURCE_MOUSE)
1809 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1810 .x(300)
1811 .y(400))
1812 .build()));
1813 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1814 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1815
1816 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001818 injectMotionEvent(mDispatcher,
1819 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1820 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1821 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1822 .x(300)
1823 .y(400))
1824 .build()));
1825 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1826
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001828 injectMotionEvent(mDispatcher,
1829 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1830 AINPUT_SOURCE_MOUSE)
1831 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1832 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1833 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1834 .x(300)
1835 .y(400))
1836 .build()));
1837 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1838 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1839
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001840 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001841 injectMotionEvent(mDispatcher,
1842 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1843 AINPUT_SOURCE_MOUSE)
1844 .buttonState(0)
1845 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1846 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1847 .x(300)
1848 .y(400))
1849 .build()));
1850 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1851 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1852
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001854 injectMotionEvent(mDispatcher,
1855 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1856 .buttonState(0)
1857 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1858 .x(300)
1859 .y(400))
1860 .build()));
1861 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1862
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001864 injectMotionEvent(mDispatcher,
1865 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
1866 AINPUT_SOURCE_MOUSE)
1867 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1868 .x(300)
1869 .y(400))
1870 .build()));
1871 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1872 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1873}
1874
Garfield Tan00f511d2019-06-12 16:55:40 -07001875TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07001876 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07001877
1878 sp<FakeWindowHandle> windowLeft =
1879 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1880 windowLeft->setFrame(Rect(0, 0, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05001881 windowLeft->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001882 sp<FakeWindowHandle> windowRight =
1883 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1884 windowRight->setFrame(Rect(600, 0, 1200, 800));
chaviw3277faf2021-05-19 16:45:23 -05001885 windowRight->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001886
1887 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1888
Arthur Hung72d8dc32020-03-28 00:48:39 +00001889 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001890
1891 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1892 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07001894 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001895 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001896 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001897 windowRight->assertNoEvents();
1898}
1899
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001900TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001901 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001902 sp<FakeWindowHandle> window =
1903 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07001904 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001905
Arthur Hung72d8dc32020-03-28 00:48:39 +00001906 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001907 setFocusedWindow(window);
1908
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001909 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001910
1911 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1912 mDispatcher->notifyKey(&keyArgs);
1913
1914 // Window should receive key down event.
1915 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1916
1917 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1918 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001919 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001920 mDispatcher->notifyDeviceReset(&args);
1921 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1922 AKEY_EVENT_FLAG_CANCELED);
1923}
1924
1925TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001926 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001927 sp<FakeWindowHandle> window =
1928 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1929
Arthur Hung72d8dc32020-03-28 00:48:39 +00001930 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001931
1932 NotifyMotionArgs motionArgs =
1933 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1934 ADISPLAY_ID_DEFAULT);
1935 mDispatcher->notifyMotion(&motionArgs);
1936
1937 // Window should receive motion down event.
1938 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1939
1940 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1941 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001942 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001943 mDispatcher->notifyDeviceReset(&args);
1944 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1945 0 /*expectedFlags*/);
1946}
1947
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001948using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
1949 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00001950
1951class TransferTouchFixture : public InputDispatcherTest,
1952 public ::testing::WithParamInterface<TransferFunction> {};
1953
1954TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07001955 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001956
1957 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001958 sp<FakeWindowHandle> firstWindow =
1959 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1960 sp<FakeWindowHandle> secondWindow =
1961 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001962
1963 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001964 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001965
1966 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001967 NotifyMotionArgs downMotionArgs =
1968 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1969 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001970 mDispatcher->notifyMotion(&downMotionArgs);
1971 // Only the first window should get the down event
1972 firstWindow->consumeMotionDown();
1973 secondWindow->assertNoEvents();
1974
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00001975 // Transfer touch to the second window
1976 TransferFunction f = GetParam();
1977 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
1978 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001979 // The first window gets cancel and the second gets down
1980 firstWindow->consumeMotionCancel();
1981 secondWindow->consumeMotionDown();
1982
1983 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001984 NotifyMotionArgs upMotionArgs =
1985 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1986 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001987 mDispatcher->notifyMotion(&upMotionArgs);
1988 // The first window gets no events and the second gets up
1989 firstWindow->assertNoEvents();
1990 secondWindow->consumeMotionUp();
1991}
1992
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00001993TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001994 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001995
1996 PointF touchPoint = {10, 10};
1997
1998 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001999 sp<FakeWindowHandle> firstWindow =
2000 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2001 sp<FakeWindowHandle> secondWindow =
2002 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002003
2004 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00002005 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002006
2007 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002008 NotifyMotionArgs downMotionArgs =
2009 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2010 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002011 mDispatcher->notifyMotion(&downMotionArgs);
2012 // Only the first window should get the down event
2013 firstWindow->consumeMotionDown();
2014 secondWindow->assertNoEvents();
2015
2016 // Send pointer down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002017 NotifyMotionArgs pointerDownMotionArgs =
2018 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2019 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2020 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2021 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002022 mDispatcher->notifyMotion(&pointerDownMotionArgs);
2023 // Only the first window should get the pointer down event
2024 firstWindow->consumeMotionPointerDown(1);
2025 secondWindow->assertNoEvents();
2026
2027 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002028 TransferFunction f = GetParam();
2029 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
2030 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002031 // The first window gets cancel and the second gets down and pointer down
2032 firstWindow->consumeMotionCancel();
2033 secondWindow->consumeMotionDown();
2034 secondWindow->consumeMotionPointerDown(1);
2035
2036 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002037 NotifyMotionArgs pointerUpMotionArgs =
2038 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2039 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2040 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2041 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002042 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2043 // The first window gets nothing and the second gets pointer up
2044 firstWindow->assertNoEvents();
2045 secondWindow->consumeMotionPointerUp(1);
2046
2047 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002048 NotifyMotionArgs upMotionArgs =
2049 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2050 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002051 mDispatcher->notifyMotion(&upMotionArgs);
2052 // The first window gets nothing and the second gets up
2053 firstWindow->assertNoEvents();
2054 secondWindow->consumeMotionUp();
2055}
2056
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002057// For the cases of single pointer touch and two pointers non-split touch, the api's
2058// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
2059// for the case where there are multiple pointers split across several windows.
2060INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
2061 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07002062 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
2063 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002064 return dispatcher->transferTouch(destChannelToken);
2065 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07002066 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
2067 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002068 return dispatcher->transferTouchFocus(from, to,
2069 false /*isDragAndDrop*/);
2070 }));
2071
Svet Ganov5d3bc372020-01-26 23:11:07 -08002072TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07002073 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08002074
2075 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002076 sp<FakeWindowHandle> firstWindow =
2077 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002078 firstWindow->setFrame(Rect(0, 0, 600, 400));
chaviw3277faf2021-05-19 16:45:23 -05002079 firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002080
2081 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002082 sp<FakeWindowHandle> secondWindow =
2083 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002084 secondWindow->setFrame(Rect(0, 400, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05002085 secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002086
2087 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00002088 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002089
2090 PointF pointInFirst = {300, 200};
2091 PointF pointInSecond = {300, 600};
2092
2093 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002094 NotifyMotionArgs firstDownMotionArgs =
2095 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2096 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002097 mDispatcher->notifyMotion(&firstDownMotionArgs);
2098 // Only the first window should get the down event
2099 firstWindow->consumeMotionDown();
2100 secondWindow->assertNoEvents();
2101
2102 // Send down to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002103 NotifyMotionArgs secondDownMotionArgs =
2104 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2105 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2106 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2107 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002108 mDispatcher->notifyMotion(&secondDownMotionArgs);
2109 // The first window gets a move and the second a down
2110 firstWindow->consumeMotionMove();
2111 secondWindow->consumeMotionDown();
2112
2113 // Transfer touch focus to the second window
2114 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
2115 // The first window gets cancel and the new gets pointer down (it already saw down)
2116 firstWindow->consumeMotionCancel();
2117 secondWindow->consumeMotionPointerDown(1);
2118
2119 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002120 NotifyMotionArgs pointerUpMotionArgs =
2121 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2122 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2123 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2124 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002125 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2126 // The first window gets nothing and the second gets pointer up
2127 firstWindow->assertNoEvents();
2128 secondWindow->consumeMotionPointerUp(1);
2129
2130 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002131 NotifyMotionArgs upMotionArgs =
2132 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2133 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002134 mDispatcher->notifyMotion(&upMotionArgs);
2135 // The first window gets nothing and the second gets up
2136 firstWindow->assertNoEvents();
2137 secondWindow->consumeMotionUp();
2138}
2139
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002140// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
2141// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
2142// touch is not supported, so the touch should continue on those windows and the transferred-to
2143// window should get nothing.
2144TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
2145 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2146
2147 // Create a non touch modal window that supports split touch
2148 sp<FakeWindowHandle> firstWindow =
2149 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2150 firstWindow->setFrame(Rect(0, 0, 600, 400));
chaviw3277faf2021-05-19 16:45:23 -05002151 firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002152
2153 // Create a non touch modal window that supports split touch
2154 sp<FakeWindowHandle> secondWindow =
2155 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
2156 secondWindow->setFrame(Rect(0, 400, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05002157 secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002158
2159 // Add the windows to the dispatcher
2160 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
2161
2162 PointF pointInFirst = {300, 200};
2163 PointF pointInSecond = {300, 600};
2164
2165 // Send down to the first window
2166 NotifyMotionArgs firstDownMotionArgs =
2167 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2168 ADISPLAY_ID_DEFAULT, {pointInFirst});
2169 mDispatcher->notifyMotion(&firstDownMotionArgs);
2170 // Only the first window should get the down event
2171 firstWindow->consumeMotionDown();
2172 secondWindow->assertNoEvents();
2173
2174 // Send down to the second window
2175 NotifyMotionArgs secondDownMotionArgs =
2176 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2177 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2178 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2179 {pointInFirst, pointInSecond});
2180 mDispatcher->notifyMotion(&secondDownMotionArgs);
2181 // The first window gets a move and the second a down
2182 firstWindow->consumeMotionMove();
2183 secondWindow->consumeMotionDown();
2184
2185 // Transfer touch focus to the second window
2186 const bool transferred = mDispatcher->transferTouch(secondWindow->getToken());
2187 // The 'transferTouch' call should not succeed, because there are 2 touched windows
2188 ASSERT_FALSE(transferred);
2189 firstWindow->assertNoEvents();
2190 secondWindow->assertNoEvents();
2191
2192 // The rest of the dispatch should proceed as normal
2193 // Send pointer up to the second window
2194 NotifyMotionArgs pointerUpMotionArgs =
2195 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2196 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2197 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2198 {pointInFirst, pointInSecond});
2199 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2200 // The first window gets MOVE and the second gets pointer up
2201 firstWindow->consumeMotionMove();
2202 secondWindow->consumeMotionUp();
2203
2204 // Send up event to the first window
2205 NotifyMotionArgs upMotionArgs =
2206 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2207 ADISPLAY_ID_DEFAULT);
2208 mDispatcher->notifyMotion(&upMotionArgs);
2209 // The first window gets nothing and the second gets up
2210 firstWindow->consumeMotionUp();
2211 secondWindow->assertNoEvents();
2212}
2213
Arthur Hungabbb9d82021-09-01 14:52:30 +00002214// This case will create two windows and one mirrored window on the default display and mirror
2215// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
2216// the windows info of second display before default display.
2217TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
2218 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2219 sp<FakeWindowHandle> firstWindowInPrimary =
2220 new FakeWindowHandle(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
2221 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
2222 firstWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2223 sp<FakeWindowHandle> secondWindowInPrimary =
2224 new FakeWindowHandle(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2225 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
2226 secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2227
2228 sp<FakeWindowHandle> mirrorWindowInPrimary =
2229 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
2230 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
2231 mirrorWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2232
2233 sp<FakeWindowHandle> firstWindowInSecondary =
2234 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2235 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
2236 firstWindowInSecondary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2237
2238 sp<FakeWindowHandle> secondWindowInSecondary =
2239 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2240 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
2241 secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2242
2243 // Update window info, let it find window handle of second display first.
2244 mDispatcher->setInputWindows(
2245 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
2246 {ADISPLAY_ID_DEFAULT,
2247 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
2248
2249 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2250 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2251 {50, 50}))
2252 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2253
2254 // Window should receive motion event.
2255 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2256
2257 // Transfer touch focus
2258 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
2259 secondWindowInPrimary->getToken()));
2260 // The first window gets cancel.
2261 firstWindowInPrimary->consumeMotionCancel();
2262 secondWindowInPrimary->consumeMotionDown();
2263
2264 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2265 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2266 ADISPLAY_ID_DEFAULT, {150, 50}))
2267 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2268 firstWindowInPrimary->assertNoEvents();
2269 secondWindowInPrimary->consumeMotionMove();
2270
2271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2272 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2273 {150, 50}))
2274 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2275 firstWindowInPrimary->assertNoEvents();
2276 secondWindowInPrimary->consumeMotionUp();
2277}
2278
2279// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
2280// 'transferTouch' api.
2281TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
2282 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2283 sp<FakeWindowHandle> firstWindowInPrimary =
2284 new FakeWindowHandle(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
2285 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
2286 firstWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2287 sp<FakeWindowHandle> secondWindowInPrimary =
2288 new FakeWindowHandle(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2289 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
2290 secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2291
2292 sp<FakeWindowHandle> mirrorWindowInPrimary =
2293 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
2294 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
2295 mirrorWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2296
2297 sp<FakeWindowHandle> firstWindowInSecondary =
2298 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2299 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
2300 firstWindowInSecondary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2301
2302 sp<FakeWindowHandle> secondWindowInSecondary =
2303 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2304 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
2305 secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2306
2307 // Update window info, let it find window handle of second display first.
2308 mDispatcher->setInputWindows(
2309 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
2310 {ADISPLAY_ID_DEFAULT,
2311 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
2312
2313 // Touch on second display.
2314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2315 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
2316 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2317
2318 // Window should receive motion event.
2319 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
2320
2321 // Transfer touch focus
2322 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken()));
2323
2324 // The first window gets cancel.
2325 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
2326 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
2327
2328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2329 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2330 SECOND_DISPLAY_ID, {150, 50}))
2331 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2332 firstWindowInPrimary->assertNoEvents();
2333 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
2334
2335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2336 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
2337 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2338 firstWindowInPrimary->assertNoEvents();
2339 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
2340}
2341
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002342TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002343 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002344 sp<FakeWindowHandle> window =
2345 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2346
Vishnu Nair47074b82020-08-14 11:54:47 -07002347 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002348 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002349 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002350
2351 window->consumeFocusEvent(true);
2352
2353 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2354 mDispatcher->notifyKey(&keyArgs);
2355
2356 // Window should receive key down event.
2357 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2358}
2359
2360TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002361 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002362 sp<FakeWindowHandle> window =
2363 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2364
Arthur Hung72d8dc32020-03-28 00:48:39 +00002365 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002366
2367 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2368 mDispatcher->notifyKey(&keyArgs);
2369 mDispatcher->waitForIdle();
2370
2371 window->assertNoEvents();
2372}
2373
2374// If a window is touchable, but does not have focus, it should receive motion events, but not keys
2375TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07002376 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002377 sp<FakeWindowHandle> window =
2378 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2379
Arthur Hung72d8dc32020-03-28 00:48:39 +00002380 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002381
2382 // Send key
2383 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2384 mDispatcher->notifyKey(&keyArgs);
2385 // Send motion
2386 NotifyMotionArgs motionArgs =
2387 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2388 ADISPLAY_ID_DEFAULT);
2389 mDispatcher->notifyMotion(&motionArgs);
2390
2391 // Window should receive only the motion event
2392 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2393 window->assertNoEvents(); // Key event or focus event will not be received
2394}
2395
arthurhungea3f4fc2020-12-21 23:18:53 +08002396TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
2397 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2398
2399 // Create first non touch modal window that supports split touch
2400 sp<FakeWindowHandle> firstWindow =
2401 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2402 firstWindow->setFrame(Rect(0, 0, 600, 400));
chaviw3277faf2021-05-19 16:45:23 -05002403 firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
arthurhungea3f4fc2020-12-21 23:18:53 +08002404
2405 // Create second non touch modal window that supports split touch
2406 sp<FakeWindowHandle> secondWindow =
2407 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
2408 secondWindow->setFrame(Rect(0, 400, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05002409 secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
arthurhungea3f4fc2020-12-21 23:18:53 +08002410
2411 // Add the windows to the dispatcher
2412 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
2413
2414 PointF pointInFirst = {300, 200};
2415 PointF pointInSecond = {300, 600};
2416
2417 // Send down to the first window
2418 NotifyMotionArgs firstDownMotionArgs =
2419 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2420 ADISPLAY_ID_DEFAULT, {pointInFirst});
2421 mDispatcher->notifyMotion(&firstDownMotionArgs);
2422 // Only the first window should get the down event
2423 firstWindow->consumeMotionDown();
2424 secondWindow->assertNoEvents();
2425
2426 // Send down to the second window
2427 NotifyMotionArgs secondDownMotionArgs =
2428 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2429 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2430 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2431 {pointInFirst, pointInSecond});
2432 mDispatcher->notifyMotion(&secondDownMotionArgs);
2433 // The first window gets a move and the second a down
2434 firstWindow->consumeMotionMove();
2435 secondWindow->consumeMotionDown();
2436
2437 // Send pointer cancel to the second window
2438 NotifyMotionArgs pointerUpMotionArgs =
2439 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2440 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2441 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2442 {pointInFirst, pointInSecond});
2443 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
2444 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2445 // The first window gets move and the second gets cancel.
2446 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
2447 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
2448
2449 // Send up event.
2450 NotifyMotionArgs upMotionArgs =
2451 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2452 ADISPLAY_ID_DEFAULT);
2453 mDispatcher->notifyMotion(&upMotionArgs);
2454 // The first window gets up and the second gets nothing.
2455 firstWindow->consumeMotionUp();
2456 secondWindow->assertNoEvents();
2457}
2458
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00002459TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
2460 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2461
2462 sp<FakeWindowHandle> window =
2463 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2464 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2465 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
2466 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
2467 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
2468
2469 window->sendTimeline(1 /*inputEventId*/, graphicsTimeline);
2470 window->assertNoEvents();
2471 mDispatcher->waitForIdle();
2472}
2473
chaviwd1c23182019-12-20 18:44:56 -08002474class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00002475public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07002476 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08002477 int32_t displayId, bool isGestureMonitor = false) {
Garfield Tan15601662020-09-22 15:32:38 -07002478 base::Result<std::unique_ptr<InputChannel>> channel =
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +00002479 dispatcher->createInputMonitor(displayId, isGestureMonitor, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07002480 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00002481 }
2482
chaviwd1c23182019-12-20 18:44:56 -08002483 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
2484
2485 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2486 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
2487 expectedDisplayId, expectedFlags);
2488 }
2489
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002490 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
2491
2492 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
2493
chaviwd1c23182019-12-20 18:44:56 -08002494 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2495 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
2496 expectedDisplayId, expectedFlags);
2497 }
2498
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002499 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2500 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE,
2501 expectedDisplayId, expectedFlags);
2502 }
2503
chaviwd1c23182019-12-20 18:44:56 -08002504 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2505 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
2506 expectedDisplayId, expectedFlags);
2507 }
2508
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002509 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2510 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2511 expectedDisplayId, expectedFlags);
2512 }
2513
Evan Rosky84f07f02021-04-16 10:42:42 -07002514 MotionEvent* consumeMotion() {
2515 InputEvent* event = mInputReceiver->consume();
2516 if (!event) {
2517 ADD_FAILURE() << "No event was produced";
2518 return nullptr;
2519 }
2520 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
2521 ADD_FAILURE() << "Received event of type " << event->getType() << " instead of motion";
2522 return nullptr;
2523 }
2524 return static_cast<MotionEvent*>(event);
2525 }
2526
chaviwd1c23182019-12-20 18:44:56 -08002527 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
2528
2529private:
2530 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00002531};
2532
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002533/**
2534 * Two entities that receive touch: A window, and a global monitor.
2535 * The touch goes to the window, and then the window disappears.
2536 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
2537 * for the monitor, as well.
2538 * 1. foregroundWindow
2539 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
2540 */
2541TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_GlobalMonitorTouchIsCanceled) {
2542 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2543 sp<FakeWindowHandle> window =
2544 new FakeWindowHandle(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2545
2546 FakeMonitorReceiver monitor =
2547 FakeMonitorReceiver(mDispatcher, "GlobalMonitor", ADISPLAY_ID_DEFAULT,
2548 false /*isGestureMonitor*/);
2549
2550 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2551 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2552 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2553 {100, 200}))
2554 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2555
2556 // Both the foreground window and the global monitor should receive the touch down
2557 window->consumeMotionDown();
2558 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2559
2560 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2561 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2562 ADISPLAY_ID_DEFAULT, {110, 200}))
2563 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2564
2565 window->consumeMotionMove();
2566 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
2567
2568 // Now the foreground window goes away
2569 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
2570 window->consumeMotionCancel();
2571 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
2572
2573 // If more events come in, there will be no more foreground window to send them to. This will
2574 // cause a cancel for the monitor, as well.
2575 ASSERT_EQ(InputEventInjectionResult::FAILED,
2576 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2577 ADISPLAY_ID_DEFAULT, {120, 200}))
2578 << "Injection should fail because the window was removed";
2579 window->assertNoEvents();
2580 // Global monitor now gets the cancel
2581 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
2582}
2583
Michael Wright3a240c42019-12-10 20:53:41 +00002584// Tests for gesture monitors
2585TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07002586 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00002587 sp<FakeWindowHandle> window =
2588 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002589 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00002590
chaviwd1c23182019-12-20 18:44:56 -08002591 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2592 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00002593
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002594 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002595 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002596 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00002597 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002598 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002599}
2600
2601TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07002602 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00002603 sp<FakeWindowHandle> window =
2604 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2605
2606 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002607 window->setFocusable(true);
Michael Wright3a240c42019-12-10 20:53:41 +00002608
Arthur Hung72d8dc32020-03-28 00:48:39 +00002609 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002610 setFocusedWindow(window);
2611
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002612 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00002613
chaviwd1c23182019-12-20 18:44:56 -08002614 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2615 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00002616
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2618 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00002619 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002620 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00002621}
2622
2623TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
Chris Yea209fde2020-07-22 13:54:51 -07002624 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00002625 sp<FakeWindowHandle> window =
2626 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002627 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00002628
chaviwd1c23182019-12-20 18:44:56 -08002629 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2630 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00002631
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002633 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002634 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00002635 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002636 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002637
2638 window->releaseChannel();
2639
chaviwd1c23182019-12-20 18:44:56 -08002640 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00002641
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002643 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002644 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08002645 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002646}
2647
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002648TEST_F(InputDispatcherTest, UnresponsiveGestureMonitor_GetsAnr) {
2649 FakeMonitorReceiver monitor =
2650 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2651 true /*isGestureMonitor*/);
2652
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002654 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
2655 std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
2656 ASSERT_TRUE(consumeSeq);
2657
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00002658 mFakePolicy->assertNotifyMonitorUnresponsiveWasCalled(DISPATCHING_TIMEOUT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002659 monitor.finishEvent(*consumeSeq);
2660 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00002661 mFakePolicy->assertNotifyMonitorResponsiveWasCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002662}
2663
Evan Rosky84f07f02021-04-16 10:42:42 -07002664// Tests for gesture monitors
2665TEST_F(InputDispatcherTest, GestureMonitor_NoWindowTransform) {
2666 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2667 sp<FakeWindowHandle> window =
2668 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2669 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2670 window->setWindowOffset(20, 40);
2671 window->setWindowTransform(0, 1, -1, 0);
2672
2673 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2674 true /*isGestureMonitor*/);
2675
2676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2677 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2678 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2679 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2680 MotionEvent* event = monitor.consumeMotion();
2681 // Even though window has transform, gesture monitor must not.
2682 ASSERT_EQ(ui::Transform(), event->getTransform());
2683}
2684
chaviw81e2bb92019-12-18 15:03:51 -08002685TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002686 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
chaviw81e2bb92019-12-18 15:03:51 -08002687 sp<FakeWindowHandle> window =
2688 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2689
Arthur Hung72d8dc32020-03-28 00:48:39 +00002690 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08002691
2692 NotifyMotionArgs motionArgs =
2693 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2694 ADISPLAY_ID_DEFAULT);
2695
2696 mDispatcher->notifyMotion(&motionArgs);
2697 // Window should receive motion down event.
2698 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2699
2700 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002701 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08002702 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
2703 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
2704 motionArgs.pointerCoords[0].getX() - 10);
2705
2706 mDispatcher->notifyMotion(&motionArgs);
2707 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
2708 0 /*expectedFlags*/);
2709}
2710
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002711/**
2712 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
2713 * the device default right away. In the test scenario, we check both the default value,
2714 * and the action of enabling / disabling.
2715 */
2716TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07002717 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002718 sp<FakeWindowHandle> window =
2719 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2720
2721 // Set focused application.
2722 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002723 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002724
2725 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00002726 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002727 setFocusedWindow(window);
2728
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002729 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2730
2731 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07002732 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002733 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002734 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
2735
2736 SCOPED_TRACE("Disable touch mode");
2737 mDispatcher->setInTouchMode(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07002738 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002739 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002740 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002741 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
2742
2743 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07002744 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002745 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002746 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
2747
2748 SCOPED_TRACE("Enable touch mode again");
2749 mDispatcher->setInTouchMode(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07002750 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002751 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002752 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002753 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2754
2755 window->assertNoEvents();
2756}
2757
Gang Wange9087892020-01-07 12:17:14 -05002758TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002759 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Gang Wange9087892020-01-07 12:17:14 -05002760 sp<FakeWindowHandle> window =
2761 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2762
2763 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002764 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05002765
Arthur Hung72d8dc32020-03-28 00:48:39 +00002766 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002767 setFocusedWindow(window);
2768
Gang Wange9087892020-01-07 12:17:14 -05002769 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2770
2771 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2772 mDispatcher->notifyKey(&keyArgs);
2773
2774 InputEvent* event = window->consume();
2775 ASSERT_NE(event, nullptr);
2776
2777 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2778 ASSERT_NE(verified, nullptr);
2779 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
2780
2781 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
2782 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
2783 ASSERT_EQ(keyArgs.source, verified->source);
2784 ASSERT_EQ(keyArgs.displayId, verified->displayId);
2785
2786 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
2787
2788 ASSERT_EQ(keyArgs.action, verifiedKey.action);
2789 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05002790 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
2791 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
2792 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
2793 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
2794 ASSERT_EQ(0, verifiedKey.repeatCount);
2795}
2796
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002797TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002798 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002799 sp<FakeWindowHandle> window =
2800 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2801
2802 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2803
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07002804 ui::Transform transform;
2805 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
2806
2807 gui::DisplayInfo displayInfo;
2808 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
2809 displayInfo.transform = transform;
2810
2811 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002812
2813 NotifyMotionArgs motionArgs =
2814 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2815 ADISPLAY_ID_DEFAULT);
2816 mDispatcher->notifyMotion(&motionArgs);
2817
2818 InputEvent* event = window->consume();
2819 ASSERT_NE(event, nullptr);
2820
2821 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2822 ASSERT_NE(verified, nullptr);
2823 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
2824
2825 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
2826 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
2827 EXPECT_EQ(motionArgs.source, verified->source);
2828 EXPECT_EQ(motionArgs.displayId, verified->displayId);
2829
2830 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
2831
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07002832 const vec2 rawXY =
2833 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
2834 motionArgs.pointerCoords[0].getXYValue());
2835 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
2836 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002837 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
2838 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
2839 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
2840 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
2841 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
2842}
2843
Prabir Pradhan664834b2021-05-20 16:00:42 -07002844TEST_F(InputDispatcherTest, NonPointerMotionEvent_JoystickAndTouchpadNotTransformed) {
yunho.shinf4a80b82020-11-16 21:13:57 +09002845 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2846 sp<FakeWindowHandle> window =
2847 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2848 const std::string name = window->getName();
2849
2850 // Window gets transformed by offset values.
2851 window->setWindowOffset(500.0f, 500.0f);
2852
2853 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2854 window->setFocusable(true);
2855
2856 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2857
2858 // First, we set focused window so that focusedWindowHandle is not null.
2859 setFocusedWindow(window);
2860
2861 // Second, we consume focus event if it is right or wrong according to onFocusChangedLocked.
2862 window->consumeFocusEvent(true);
2863
Prabir Pradhan664834b2021-05-20 16:00:42 -07002864 constexpr const std::array nonTransformedSources = {std::pair(AINPUT_SOURCE_TOUCHPAD,
2865 AMOTION_EVENT_ACTION_DOWN),
2866 std::pair(AINPUT_SOURCE_JOYSTICK,
2867 AMOTION_EVENT_ACTION_MOVE)};
2868 for (const auto& [source, action] : nonTransformedSources) {
2869 const NotifyMotionArgs motionArgs = generateMotionArgs(action, source, ADISPLAY_ID_DEFAULT);
Prabir Pradhanbd527712021-03-09 19:17:09 -08002870 mDispatcher->notifyMotion(&motionArgs);
yunho.shinf4a80b82020-11-16 21:13:57 +09002871
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00002872 MotionEvent* event = window->consumeMotion();
Prabir Pradhanbd527712021-03-09 19:17:09 -08002873 ASSERT_NE(event, nullptr);
yunho.shinf4a80b82020-11-16 21:13:57 +09002874
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00002875 const MotionEvent& motionEvent = *event;
Prabir Pradhan664834b2021-05-20 16:00:42 -07002876 EXPECT_EQ(action, motionEvent.getAction());
Prabir Pradhanbd527712021-03-09 19:17:09 -08002877 EXPECT_EQ(motionArgs.pointerCount, motionEvent.getPointerCount());
yunho.shinf4a80b82020-11-16 21:13:57 +09002878
Prabir Pradhanbd527712021-03-09 19:17:09 -08002879 float expectedX = motionArgs.pointerCoords[0].getX();
2880 float expectedY = motionArgs.pointerCoords[0].getY();
yunho.shinf4a80b82020-11-16 21:13:57 +09002881
Prabir Pradhanbd527712021-03-09 19:17:09 -08002882 // Ensure the axis values from the final motion event are not transformed.
2883 EXPECT_EQ(expectedX, motionEvent.getX(0))
2884 << "expected " << expectedX << " for x coord of " << name.c_str() << ", got "
2885 << motionEvent.getX(0);
2886 EXPECT_EQ(expectedY, motionEvent.getY(0))
2887 << "expected " << expectedY << " for y coord of " << name.c_str() << ", got "
2888 << motionEvent.getY(0);
2889 // Ensure the raw and transformed axis values for the motion event are the same.
2890 EXPECT_EQ(motionEvent.getRawX(0), motionEvent.getX(0))
2891 << "expected raw and transformed X-axis values to be equal";
2892 EXPECT_EQ(motionEvent.getRawY(0), motionEvent.getY(0))
2893 << "expected raw and transformed Y-axis values to be equal";
2894 }
yunho.shinf4a80b82020-11-16 21:13:57 +09002895}
2896
chaviw09c8d2d2020-08-24 15:48:26 -07002897/**
2898 * Ensure that separate calls to sign the same data are generating the same key.
2899 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
2900 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
2901 * tests.
2902 */
2903TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
2904 KeyEvent event = getTestKeyEvent();
2905 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2906
2907 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
2908 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
2909 ASSERT_EQ(hmac1, hmac2);
2910}
2911
2912/**
2913 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
2914 */
2915TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
2916 KeyEvent event = getTestKeyEvent();
2917 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2918 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
2919
2920 verifiedEvent.deviceId += 1;
2921 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2922
2923 verifiedEvent.source += 1;
2924 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2925
2926 verifiedEvent.eventTimeNanos += 1;
2927 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2928
2929 verifiedEvent.displayId += 1;
2930 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2931
2932 verifiedEvent.action += 1;
2933 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2934
2935 verifiedEvent.downTimeNanos += 1;
2936 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2937
2938 verifiedEvent.flags += 1;
2939 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2940
2941 verifiedEvent.keyCode += 1;
2942 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2943
2944 verifiedEvent.scanCode += 1;
2945 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2946
2947 verifiedEvent.metaState += 1;
2948 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2949
2950 verifiedEvent.repeatCount += 1;
2951 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2952}
2953
Vishnu Nair958da932020-08-21 17:12:37 -07002954TEST_F(InputDispatcherTest, SetFocusedWindow) {
2955 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2956 sp<FakeWindowHandle> windowTop =
2957 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2958 sp<FakeWindowHandle> windowSecond =
2959 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2960 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2961
2962 // Top window is also focusable but is not granted focus.
2963 windowTop->setFocusable(true);
2964 windowSecond->setFocusable(true);
2965 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2966 setFocusedWindow(windowSecond);
2967
2968 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002969 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2970 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002971
2972 // Focused window should receive event.
2973 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2974 windowTop->assertNoEvents();
2975}
2976
2977TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
2978 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2979 sp<FakeWindowHandle> window =
2980 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2981 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2982
2983 window->setFocusable(true);
2984 // Release channel for window is no longer valid.
2985 window->releaseChannel();
2986 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2987 setFocusedWindow(window);
2988
2989 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002990 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2991 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002992
2993 // window channel is invalid, so it should not receive any input event.
2994 window->assertNoEvents();
2995}
2996
2997TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
2998 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2999 sp<FakeWindowHandle> window =
3000 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3001 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3002
3003 // Window is not focusable.
3004 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3005 setFocusedWindow(window);
3006
3007 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003008 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3009 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003010
3011 // window is invalid, so it should not receive any input event.
3012 window->assertNoEvents();
3013}
3014
3015TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
3016 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3017 sp<FakeWindowHandle> windowTop =
3018 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
3019 sp<FakeWindowHandle> windowSecond =
3020 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3021 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3022
3023 windowTop->setFocusable(true);
3024 windowSecond->setFocusable(true);
3025 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3026 setFocusedWindow(windowTop);
3027 windowTop->consumeFocusEvent(true);
3028
3029 setFocusedWindow(windowSecond, windowTop);
3030 windowSecond->consumeFocusEvent(true);
3031 windowTop->consumeFocusEvent(false);
3032
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3034 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003035
3036 // Focused window should receive event.
3037 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
3038}
3039
3040TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
3041 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3042 sp<FakeWindowHandle> windowTop =
3043 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
3044 sp<FakeWindowHandle> windowSecond =
3045 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3046 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3047
3048 windowTop->setFocusable(true);
3049 windowSecond->setFocusable(true);
3050 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3051 setFocusedWindow(windowSecond, windowTop);
3052
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003053 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3054 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003055
3056 // Event should be dropped.
3057 windowTop->assertNoEvents();
3058 windowSecond->assertNoEvents();
3059}
3060
3061TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
3062 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3063 sp<FakeWindowHandle> window =
3064 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3065 sp<FakeWindowHandle> previousFocusedWindow =
3066 new FakeWindowHandle(application, mDispatcher, "previousFocusedWindow",
3067 ADISPLAY_ID_DEFAULT);
3068 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3069
3070 window->setFocusable(true);
3071 previousFocusedWindow->setFocusable(true);
3072 window->setVisible(false);
3073 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
3074 setFocusedWindow(previousFocusedWindow);
3075 previousFocusedWindow->consumeFocusEvent(true);
3076
3077 // Requesting focus on invisible window takes focus from currently focused window.
3078 setFocusedWindow(window);
3079 previousFocusedWindow->consumeFocusEvent(false);
3080
3081 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003082 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07003083 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003084 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07003085
3086 // Window does not get focus event or key down.
3087 window->assertNoEvents();
3088
3089 // Window becomes visible.
3090 window->setVisible(true);
3091 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3092
3093 // Window receives focus event.
3094 window->consumeFocusEvent(true);
3095 // Focused window receives key down.
3096 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3097}
3098
Vishnu Nair599f1412021-06-21 10:39:58 -07003099TEST_F(InputDispatcherTest, DisplayRemoved) {
3100 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3101 sp<FakeWindowHandle> window =
3102 new FakeWindowHandle(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
3103 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3104
3105 // window is granted focus.
3106 window->setFocusable(true);
3107 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3108 setFocusedWindow(window);
3109 window->consumeFocusEvent(true);
3110
3111 // When a display is removed window loses focus.
3112 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
3113 window->consumeFocusEvent(false);
3114}
3115
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003116/**
3117 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
3118 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
3119 * of the 'slipperyEnterWindow'.
3120 *
3121 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
3122 * a way so that the touched location is no longer covered by the top window.
3123 *
3124 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
3125 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
3126 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
3127 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
3128 * with ACTION_DOWN).
3129 * Thus, the touch has been transferred from the top window into the bottom window, because the top
3130 * window moved itself away from the touched location and had Flag::SLIPPERY.
3131 *
3132 * Even though the top window moved away from the touched location, it is still obscuring the bottom
3133 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
3134 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
3135 *
3136 * In this test, we ensure that the event received by the bottom window has
3137 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
3138 */
3139TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
3140 constexpr int32_t SLIPPERY_PID = INJECTOR_PID + 1;
3141 constexpr int32_t SLIPPERY_UID = INJECTOR_UID + 1;
3142
3143 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3144 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3145
3146 sp<FakeWindowHandle> slipperyExitWindow =
3147 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviw3277faf2021-05-19 16:45:23 -05003148 slipperyExitWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SLIPPERY);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003149 // Make sure this one overlaps the bottom window
3150 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
3151 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
3152 // one. Windows with the same owner are not considered to be occluding each other.
3153 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
3154
3155 sp<FakeWindowHandle> slipperyEnterWindow =
3156 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3157 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
3158
3159 mDispatcher->setInputWindows(
3160 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
3161
3162 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
3163 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3164 ADISPLAY_ID_DEFAULT, {{50, 50}});
3165 mDispatcher->notifyMotion(&args);
3166 slipperyExitWindow->consumeMotionDown();
3167 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
3168 mDispatcher->setInputWindows(
3169 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
3170
3171 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3172 ADISPLAY_ID_DEFAULT, {{51, 51}});
3173 mDispatcher->notifyMotion(&args);
3174
3175 slipperyExitWindow->consumeMotionCancel();
3176
3177 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
3178 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
3179}
3180
Garfield Tan1c7bc862020-01-28 13:24:04 -08003181class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
3182protected:
3183 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
3184 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
3185
Chris Yea209fde2020-07-22 13:54:51 -07003186 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003187 sp<FakeWindowHandle> mWindow;
3188
3189 virtual void SetUp() override {
3190 mFakePolicy = new FakeInputDispatcherPolicy();
3191 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07003192 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003193 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
3194 ASSERT_EQ(OK, mDispatcher->start());
3195
3196 setUpWindow();
3197 }
3198
3199 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07003200 mApp = std::make_shared<FakeApplicationHandle>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08003201 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
3202
Vishnu Nair47074b82020-08-14 11:54:47 -07003203 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003204 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003205 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003206 mWindow->consumeFocusEvent(true);
3207 }
3208
Chris Ye2ad95392020-09-01 13:44:44 -07003209 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08003210 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07003211 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003212 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
3213 mDispatcher->notifyKey(&keyArgs);
3214
3215 // Window should receive key down event.
3216 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3217 }
3218
3219 void expectKeyRepeatOnce(int32_t repeatCount) {
3220 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
3221 InputEvent* repeatEvent = mWindow->consume();
3222 ASSERT_NE(nullptr, repeatEvent);
3223
3224 uint32_t eventType = repeatEvent->getType();
3225 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
3226
3227 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
3228 uint32_t eventAction = repeatKeyEvent->getAction();
3229 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
3230 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
3231 }
3232
Chris Ye2ad95392020-09-01 13:44:44 -07003233 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08003234 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07003235 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003236 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
3237 mDispatcher->notifyKey(&keyArgs);
3238
3239 // Window should receive key down event.
3240 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
3241 0 /*expectedFlags*/);
3242 }
3243};
3244
3245TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Chris Ye2ad95392020-09-01 13:44:44 -07003246 sendAndConsumeKeyDown(1 /* deviceId */);
3247 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3248 expectKeyRepeatOnce(repeatCount);
3249 }
3250}
3251
3252TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
3253 sendAndConsumeKeyDown(1 /* deviceId */);
3254 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3255 expectKeyRepeatOnce(repeatCount);
3256 }
3257 sendAndConsumeKeyDown(2 /* deviceId */);
3258 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08003259 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3260 expectKeyRepeatOnce(repeatCount);
3261 }
3262}
3263
3264TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Chris Ye2ad95392020-09-01 13:44:44 -07003265 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003266 expectKeyRepeatOnce(1 /*repeatCount*/);
Chris Ye2ad95392020-09-01 13:44:44 -07003267 sendAndConsumeKeyUp(1 /* deviceId */);
3268 mWindow->assertNoEvents();
3269}
3270
3271TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
3272 sendAndConsumeKeyDown(1 /* deviceId */);
3273 expectKeyRepeatOnce(1 /*repeatCount*/);
3274 sendAndConsumeKeyDown(2 /* deviceId */);
3275 expectKeyRepeatOnce(1 /*repeatCount*/);
3276 // Stale key up from device 1.
3277 sendAndConsumeKeyUp(1 /* deviceId */);
3278 // Device 2 is still down, keep repeating
3279 expectKeyRepeatOnce(2 /*repeatCount*/);
3280 expectKeyRepeatOnce(3 /*repeatCount*/);
3281 // Device 2 key up
3282 sendAndConsumeKeyUp(2 /* deviceId */);
3283 mWindow->assertNoEvents();
3284}
3285
3286TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
3287 sendAndConsumeKeyDown(1 /* deviceId */);
3288 expectKeyRepeatOnce(1 /*repeatCount*/);
3289 sendAndConsumeKeyDown(2 /* deviceId */);
3290 expectKeyRepeatOnce(1 /*repeatCount*/);
3291 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
3292 sendAndConsumeKeyUp(2 /* deviceId */);
3293 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08003294 mWindow->assertNoEvents();
3295}
3296
liushenxiang42232912021-05-21 20:24:09 +08003297TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
3298 sendAndConsumeKeyDown(DEVICE_ID);
3299 expectKeyRepeatOnce(1 /*repeatCount*/);
3300 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
3301 mDispatcher->notifyDeviceReset(&args);
3302 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
3303 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
3304 mWindow->assertNoEvents();
3305}
3306
Garfield Tan1c7bc862020-01-28 13:24:04 -08003307TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Chris Ye2ad95392020-09-01 13:44:44 -07003308 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003309 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3310 InputEvent* repeatEvent = mWindow->consume();
3311 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
3312 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
3313 IdGenerator::getSource(repeatEvent->getId()));
3314 }
3315}
3316
3317TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Chris Ye2ad95392020-09-01 13:44:44 -07003318 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003319
3320 std::unordered_set<int32_t> idSet;
3321 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3322 InputEvent* repeatEvent = mWindow->consume();
3323 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
3324 int32_t id = repeatEvent->getId();
3325 EXPECT_EQ(idSet.end(), idSet.find(id));
3326 idSet.insert(id);
3327 }
3328}
3329
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003330/* Test InputDispatcher for MultiDisplay */
3331class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
3332public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003333 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003334 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08003335
Chris Yea209fde2020-07-22 13:54:51 -07003336 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003337 windowInPrimary =
3338 new FakeWindowHandle(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003339
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003340 // Set focus window for primary display, but focused display would be second one.
3341 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07003342 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003343 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003344 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003345 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08003346
Chris Yea209fde2020-07-22 13:54:51 -07003347 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003348 windowInSecondary =
3349 new FakeWindowHandle(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003350 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003351 // Set focus display to second one.
3352 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
3353 // Set focus window for second display.
3354 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07003355 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003356 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003357 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003358 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003359 }
3360
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003361 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003362 InputDispatcherTest::TearDown();
3363
Chris Yea209fde2020-07-22 13:54:51 -07003364 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003365 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07003366 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003367 windowInSecondary.clear();
3368 }
3369
3370protected:
Chris Yea209fde2020-07-22 13:54:51 -07003371 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003372 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07003373 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003374 sp<FakeWindowHandle> windowInSecondary;
3375};
3376
3377TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
3378 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003379 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3380 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3381 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003382 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08003383 windowInSecondary->assertNoEvents();
3384
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003385 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003386 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3387 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
3388 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08003389 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003390 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08003391}
3392
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003393TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08003394 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003395 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3396 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003397 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003398 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08003399 windowInSecondary->assertNoEvents();
3400
3401 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003403 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08003404 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003405 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08003406
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003407 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00003408 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08003409
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003410 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003411 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
3412 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08003413
3414 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003415 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003416 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08003417 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003418 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08003419 windowInSecondary->assertNoEvents();
3420}
3421
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003422// Test per-display input monitors for motion event.
3423TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08003424 FakeMonitorReceiver monitorInPrimary =
3425 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
3426 FakeMonitorReceiver monitorInSecondary =
3427 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003428
3429 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003430 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3431 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3432 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003433 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08003434 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003435 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003436 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003437
3438 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3440 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
3441 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003442 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003443 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003444 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08003445 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003446
3447 // Test inject a non-pointer motion event.
3448 // If specific a display, it will dispatch to the focused window of particular display,
3449 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3451 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
3452 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003453 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003454 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003455 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08003456 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003457}
3458
3459// Test per-display input monitors for key event.
3460TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003461 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08003462 FakeMonitorReceiver monitorInPrimary =
3463 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
3464 FakeMonitorReceiver monitorInSecondary =
3465 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003466
3467 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003468 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3469 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003470 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003471 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003472 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08003473 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003474}
3475
Vishnu Nair958da932020-08-21 17:12:37 -07003476TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
3477 sp<FakeWindowHandle> secondWindowInPrimary =
3478 new FakeWindowHandle(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
3479 secondWindowInPrimary->setFocusable(true);
3480 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
3481 setFocusedWindow(secondWindowInPrimary);
3482 windowInPrimary->consumeFocusEvent(false);
3483 secondWindowInPrimary->consumeFocusEvent(true);
3484
3485 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
3487 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003488 windowInPrimary->assertNoEvents();
3489 windowInSecondary->assertNoEvents();
3490 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3491}
3492
Jackal Guof9696682018-10-05 12:23:23 +08003493class InputFilterTest : public InputDispatcherTest {
3494protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07003495 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
3496 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08003497 NotifyMotionArgs motionArgs;
3498
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003499 motionArgs =
3500 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08003501 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003502 motionArgs =
3503 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08003504 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003505 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08003506 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07003507 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
3508 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08003509 } else {
3510 mFakePolicy->assertFilterInputEventWasNotCalled();
3511 }
3512 }
3513
3514 void testNotifyKey(bool expectToBeFiltered) {
3515 NotifyKeyArgs keyArgs;
3516
3517 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
3518 mDispatcher->notifyKey(&keyArgs);
3519 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
3520 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003521 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08003522
3523 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08003524 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08003525 } else {
3526 mFakePolicy->assertFilterInputEventWasNotCalled();
3527 }
3528 }
3529};
3530
3531// Test InputFilter for MotionEvent
3532TEST_F(InputFilterTest, MotionEvent_InputFilter) {
3533 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
3534 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
3535 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
3536
3537 // Enable InputFilter
3538 mDispatcher->setInputFilterEnabled(true);
3539 // Test touch on both primary and second display, and check if both events are filtered.
3540 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
3541 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
3542
3543 // Disable InputFilter
3544 mDispatcher->setInputFilterEnabled(false);
3545 // Test touch on both primary and second display, and check if both events aren't filtered.
3546 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
3547 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
3548}
3549
3550// Test InputFilter for KeyEvent
3551TEST_F(InputFilterTest, KeyEvent_InputFilter) {
3552 // Since the InputFilter is disabled by default, check if key event aren't filtered.
3553 testNotifyKey(/*expectToBeFiltered*/ false);
3554
3555 // Enable InputFilter
3556 mDispatcher->setInputFilterEnabled(true);
3557 // Send a key event, and check if it is filtered.
3558 testNotifyKey(/*expectToBeFiltered*/ true);
3559
3560 // Disable InputFilter
3561 mDispatcher->setInputFilterEnabled(false);
3562 // Send a key event, and check if it isn't filtered.
3563 testNotifyKey(/*expectToBeFiltered*/ false);
3564}
3565
Prabir Pradhan81420cc2021-09-06 10:28:50 -07003566// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
3567// logical display coordinate space.
3568TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
3569 ui::Transform firstDisplayTransform;
3570 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
3571 ui::Transform secondDisplayTransform;
3572 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
3573
3574 std::vector<gui::DisplayInfo> displayInfos(2);
3575 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
3576 displayInfos[0].transform = firstDisplayTransform;
3577 displayInfos[1].displayId = SECOND_DISPLAY_ID;
3578 displayInfos[1].transform = secondDisplayTransform;
3579
3580 mDispatcher->onWindowInfosChanged({}, displayInfos);
3581
3582 // Enable InputFilter
3583 mDispatcher->setInputFilterEnabled(true);
3584
3585 // Ensure the correct transforms are used for the displays.
3586 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
3587 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
3588}
3589
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003590class InputFilterInjectionPolicyTest : public InputDispatcherTest {
3591protected:
3592 virtual void SetUp() override {
3593 InputDispatcherTest::SetUp();
3594
3595 /**
3596 * We don't need to enable input filter to test the injected event policy, but we enabled it
3597 * here to make the tests more realistic, since this policy only matters when inputfilter is
3598 * on.
3599 */
3600 mDispatcher->setInputFilterEnabled(true);
3601
3602 std::shared_ptr<InputApplicationHandle> application =
3603 std::make_shared<FakeApplicationHandle>();
3604 mWindow =
3605 new FakeWindowHandle(application, mDispatcher, "Test Window", ADISPLAY_ID_DEFAULT);
3606
3607 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3608 mWindow->setFocusable(true);
3609 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3610 setFocusedWindow(mWindow);
3611 mWindow->consumeFocusEvent(true);
3612 }
3613
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003614 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
3615 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003616 KeyEvent event;
3617
3618 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3619 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
3620 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
3621 KEY_A, AMETA_NONE, 0 /*repeatCount*/, eventTime, eventTime);
3622 const int32_t additionalPolicyFlags =
3623 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
3624 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3625 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
3626 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
3627 policyFlags | additionalPolicyFlags));
3628
3629 InputEvent* received = mWindow->consume();
3630 ASSERT_NE(nullptr, received);
3631 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003632 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_KEY);
3633 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
3634 ASSERT_EQ(flags, keyEvent.getFlags());
3635 }
3636
3637 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
3638 int32_t flags) {
3639 MotionEvent event;
3640 PointerProperties pointerProperties[1];
3641 PointerCoords pointerCoords[1];
3642 pointerProperties[0].clear();
3643 pointerProperties[0].id = 0;
3644 pointerCoords[0].clear();
3645 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
3646 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
3647
3648 ui::Transform identityTransform;
3649 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3650 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
3651 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
3652 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
3653 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07003654 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07003655 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003656 /*pointerCount*/ 1, pointerProperties, pointerCoords);
3657
3658 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
3659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3660 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
3661 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
3662 policyFlags | additionalPolicyFlags));
3663
3664 InputEvent* received = mWindow->consume();
3665 ASSERT_NE(nullptr, received);
3666 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
3667 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_MOTION);
3668 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
3669 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003670 }
3671
3672private:
3673 sp<FakeWindowHandle> mWindow;
3674};
3675
3676TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003677 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
3678 // filter. Without it, the event will no different from a regularly injected event, and the
3679 // injected device id will be overwritten.
3680 testInjectedKey(POLICY_FLAG_FILTERED, 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3681 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003682}
3683
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003684TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003685 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003686 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3687 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3688}
3689
3690TEST_F(InputFilterInjectionPolicyTest,
3691 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
3692 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
3693 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3694 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003695}
3696
3697TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
3698 testInjectedKey(0 /*policyFlags*/, 3 /*injectedDeviceId*/,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003699 VIRTUAL_KEYBOARD_ID /*resolvedDeviceId*/, 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003700}
3701
chaviwfd6d3512019-03-25 13:23:49 -07003702class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003703 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07003704 InputDispatcherTest::SetUp();
3705
Chris Yea209fde2020-07-22 13:54:51 -07003706 std::shared_ptr<FakeApplicationHandle> application =
3707 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003708 mUnfocusedWindow =
3709 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07003710 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
3711 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3712 // window.
chaviw3277faf2021-05-19 16:45:23 -05003713 mUnfocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07003714
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003715 mFocusedWindow =
3716 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3717 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05003718 mFocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07003719
3720 // Set focused application.
3721 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07003722 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07003723
3724 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00003725 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003726 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003727 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07003728 }
3729
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003730 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07003731 InputDispatcherTest::TearDown();
3732
3733 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003734 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07003735 }
3736
3737protected:
3738 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003739 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003740 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07003741};
3742
3743// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
3744// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
3745// the onPointerDownOutsideFocus callback.
3746TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003747 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003748 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3749 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003750 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003751 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07003752
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003753 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07003754 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
3755}
3756
3757// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
3758// DOWN on the window that doesn't have focus. Ensure no window received the
3759// onPointerDownOutsideFocus callback.
3760TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003762 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003763 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003764 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07003765
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003766 ASSERT_TRUE(mDispatcher->waitForIdle());
3767 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07003768}
3769
3770// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
3771// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
3772TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003773 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3774 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003775 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003776 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07003777
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003778 ASSERT_TRUE(mDispatcher->waitForIdle());
3779 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07003780}
3781
3782// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
3783// DOWN on the window that already has focus. Ensure no window received the
3784// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003785TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003786 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003787 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003788 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003789 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003790 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07003791
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003792 ASSERT_TRUE(mDispatcher->waitForIdle());
3793 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07003794}
3795
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08003796// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
3797// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
3798TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
3799 const MotionEvent event =
3800 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3801 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
3802 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(20).y(20))
3803 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
3804 .build();
3805 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
3806 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3807 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
3808
3809 ASSERT_TRUE(mDispatcher->waitForIdle());
3810 mFakePolicy->assertOnPointerDownWasNotCalled();
3811 // Ensure that the unfocused window did not receive any FOCUS events.
3812 mUnfocusedWindow->assertNoEvents();
3813}
3814
chaviwaf87b3e2019-10-01 16:59:28 -07003815// These tests ensures we can send touch events to a single client when there are multiple input
3816// windows that point to the same client token.
3817class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
3818 virtual void SetUp() override {
3819 InputDispatcherTest::SetUp();
3820
Chris Yea209fde2020-07-22 13:54:51 -07003821 std::shared_ptr<FakeApplicationHandle> application =
3822 std::make_shared<FakeApplicationHandle>();
chaviwaf87b3e2019-10-01 16:59:28 -07003823 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
3824 ADISPLAY_ID_DEFAULT);
3825 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
3826 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
chaviw3277faf2021-05-19 16:45:23 -05003827 mWindow1->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07003828 mWindow1->setFrame(Rect(0, 0, 100, 100));
3829
3830 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
3831 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviw3277faf2021-05-19 16:45:23 -05003832 mWindow2->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07003833 mWindow2->setFrame(Rect(100, 100, 200, 200));
3834
Arthur Hung72d8dc32020-03-28 00:48:39 +00003835 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07003836 }
3837
3838protected:
3839 sp<FakeWindowHandle> mWindow1;
3840 sp<FakeWindowHandle> mWindow2;
3841
3842 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05003843 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07003844 vec2 vals = windowInfo->transform.transform(point.x, point.y);
3845 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07003846 }
3847
3848 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
3849 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003850 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07003851 InputEvent* event = window->consume();
3852
3853 ASSERT_NE(nullptr, event) << name.c_str()
3854 << ": consumer should have returned non-NULL event.";
3855
3856 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
3857 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
3858 << " event, got " << inputEventTypeToString(event->getType()) << " event";
3859
3860 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003861 assertMotionAction(expectedAction, motionEvent.getAction());
chaviwaf87b3e2019-10-01 16:59:28 -07003862
3863 for (size_t i = 0; i < points.size(); i++) {
3864 float expectedX = points[i].x;
3865 float expectedY = points[i].y;
3866
3867 EXPECT_EQ(expectedX, motionEvent.getX(i))
3868 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
3869 << ", got " << motionEvent.getX(i);
3870 EXPECT_EQ(expectedY, motionEvent.getY(i))
3871 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
3872 << ", got " << motionEvent.getY(i);
3873 }
3874 }
chaviw9eaa22c2020-07-01 16:21:27 -07003875
3876 void touchAndAssertPositions(int32_t action, std::vector<PointF> touchedPoints,
3877 std::vector<PointF> expectedPoints) {
3878 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
3879 ADISPLAY_ID_DEFAULT, touchedPoints);
3880 mDispatcher->notifyMotion(&motionArgs);
3881
3882 // Always consume from window1 since it's the window that has the InputReceiver
3883 consumeMotionEvent(mWindow1, action, expectedPoints);
3884 }
chaviwaf87b3e2019-10-01 16:59:28 -07003885};
3886
3887TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
3888 // Touch Window 1
3889 PointF touchedPoint = {10, 10};
3890 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003891 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003892
3893 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07003894 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003895
3896 // Touch Window 2
3897 touchedPoint = {150, 150};
3898 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003899 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003900}
3901
chaviw9eaa22c2020-07-01 16:21:27 -07003902TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
3903 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07003904 mWindow2->setWindowScale(0.5f, 0.5f);
3905
3906 // Touch Window 1
3907 PointF touchedPoint = {10, 10};
3908 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003909 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003910 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07003911 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003912
3913 // Touch Window 2
3914 touchedPoint = {150, 150};
3915 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003916 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
3917 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003918
chaviw9eaa22c2020-07-01 16:21:27 -07003919 // Update the transform so rotation is set
3920 mWindow2->setWindowTransform(0, -1, 1, 0);
3921 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
3922 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003923}
3924
chaviw9eaa22c2020-07-01 16:21:27 -07003925TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003926 mWindow2->setWindowScale(0.5f, 0.5f);
3927
3928 // Touch Window 1
3929 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3930 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003931 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003932
3933 // Touch Window 2
3934 int32_t actionPointerDown =
3935 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003936 touchedPoints.push_back(PointF{150, 150});
3937 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3938 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003939
chaviw9eaa22c2020-07-01 16:21:27 -07003940 // Release Window 2
3941 int32_t actionPointerUp =
3942 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3943 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
3944 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003945
chaviw9eaa22c2020-07-01 16:21:27 -07003946 // Update the transform so rotation is set for Window 2
3947 mWindow2->setWindowTransform(0, -1, 1, 0);
3948 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3949 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003950}
3951
chaviw9eaa22c2020-07-01 16:21:27 -07003952TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003953 mWindow2->setWindowScale(0.5f, 0.5f);
3954
3955 // Touch Window 1
3956 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3957 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003958 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003959
3960 // Touch Window 2
3961 int32_t actionPointerDown =
3962 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003963 touchedPoints.push_back(PointF{150, 150});
3964 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003965
chaviw9eaa22c2020-07-01 16:21:27 -07003966 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003967
3968 // Move both windows
3969 touchedPoints = {{20, 20}, {175, 175}};
3970 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3971 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3972
chaviw9eaa22c2020-07-01 16:21:27 -07003973 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003974
chaviw9eaa22c2020-07-01 16:21:27 -07003975 // Release Window 2
3976 int32_t actionPointerUp =
3977 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3978 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
3979 expectedPoints.pop_back();
3980
3981 // Touch Window 2
3982 mWindow2->setWindowTransform(0, -1, 1, 0);
3983 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3984 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
3985
3986 // Move both windows
3987 touchedPoints = {{20, 20}, {175, 175}};
3988 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3989 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3990
3991 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003992}
3993
3994TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
3995 mWindow1->setWindowScale(0.5f, 0.5f);
3996
3997 // Touch Window 1
3998 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3999 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07004000 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004001
4002 // Touch Window 2
4003 int32_t actionPointerDown =
4004 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07004005 touchedPoints.push_back(PointF{150, 150});
4006 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004007
chaviw9eaa22c2020-07-01 16:21:27 -07004008 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004009
4010 // Move both windows
4011 touchedPoints = {{20, 20}, {175, 175}};
4012 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
4013 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
4014
chaviw9eaa22c2020-07-01 16:21:27 -07004015 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004016}
4017
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004018class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
4019 virtual void SetUp() override {
4020 InputDispatcherTest::SetUp();
4021
Chris Yea209fde2020-07-22 13:54:51 -07004022 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004023 mApplication->setDispatchingTimeout(20ms);
4024 mWindow =
4025 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
4026 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05004027 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07004028 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004029 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
4030 // window.
chaviw3277faf2021-05-19 16:45:23 -05004031 mWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004032
4033 // Set focused application.
4034 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
4035
4036 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004037 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004038 mWindow->consumeFocusEvent(true);
4039 }
4040
4041 virtual void TearDown() override {
4042 InputDispatcherTest::TearDown();
4043 mWindow.clear();
4044 }
4045
4046protected:
Chris Yea209fde2020-07-22 13:54:51 -07004047 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004048 sp<FakeWindowHandle> mWindow;
4049 static constexpr PointF WINDOW_LOCATION = {20, 20};
4050
4051 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004053 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4054 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004055 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004056 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4057 WINDOW_LOCATION));
4058 }
4059};
4060
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004061// Send a tap and respond, which should not cause an ANR.
4062TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
4063 tapOnWindow();
4064 mWindow->consumeMotionDown();
4065 mWindow->consumeMotionUp();
4066 ASSERT_TRUE(mDispatcher->waitForIdle());
4067 mFakePolicy->assertNotifyAnrWasNotCalled();
4068}
4069
4070// Send a regular key and respond, which should not cause an ANR.
4071TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004072 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004073 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
4074 ASSERT_TRUE(mDispatcher->waitForIdle());
4075 mFakePolicy->assertNotifyAnrWasNotCalled();
4076}
4077
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004078TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
4079 mWindow->setFocusable(false);
4080 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4081 mWindow->consumeFocusEvent(false);
4082
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004083 InputEventInjectionResult result =
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004084 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004085 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
4086 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004087 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004088 // Key will not go to window because we have no focused window.
4089 // The 'no focused window' ANR timer should start instead.
4090
4091 // Now, the focused application goes away.
4092 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
4093 // The key should get dropped and there should be no ANR.
4094
4095 ASSERT_TRUE(mDispatcher->waitForIdle());
4096 mFakePolicy->assertNotifyAnrWasNotCalled();
4097}
4098
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004099// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004100// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
4101// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004102TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004103 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004104 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4105 WINDOW_LOCATION));
4106
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004107 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
4108 ASSERT_TRUE(sequenceNum);
4109 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004110 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004111
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004112 mWindow->finishEvent(*sequenceNum);
4113 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
4114 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004115 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004116 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004117}
4118
4119// Send a key to the app and have the app not respond right away.
4120TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
4121 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004123 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
4124 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004125 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004126 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004127 ASSERT_TRUE(mDispatcher->waitForIdle());
4128}
4129
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004130// We have a focused application, but no focused window
4131TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004132 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004133 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4134 mWindow->consumeFocusEvent(false);
4135
4136 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004137 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004138 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4139 WINDOW_LOCATION));
4140 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
4141 mDispatcher->waitForIdle();
4142 mFakePolicy->assertNotifyAnrWasNotCalled();
4143
4144 // Once a focused event arrives, we get an ANR for this application
4145 // We specify the injection timeout to be smaller than the application timeout, to ensure that
4146 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004147 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004148 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004149 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004150 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004151 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004152 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004153 ASSERT_TRUE(mDispatcher->waitForIdle());
4154}
4155
4156// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004157// Make sure that we don't notify policy twice about the same ANR.
4158TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004159 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004160 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4161 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004162
4163 // Once a focused event arrives, we get an ANR for this application
4164 // We specify the injection timeout to be smaller than the application timeout, to ensure that
4165 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004166 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004167 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004168 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004169 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004170 const std::chrono::duration appTimeout =
4171 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004172 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004173
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004174 std::this_thread::sleep_for(appTimeout);
4175 // ANR should not be raised again. It is up to policy to do that if it desires.
4176 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004177
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004178 // If we now get a focused window, the ANR should stop, but the policy handles that via
4179 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004180 ASSERT_TRUE(mDispatcher->waitForIdle());
4181}
4182
4183// We have a focused application, but no focused window
4184TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004185 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004186 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4187 mWindow->consumeFocusEvent(false);
4188
4189 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004190 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004191 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004192 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
4193 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004194
4195 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004196 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004197
4198 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004199 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004200 ASSERT_TRUE(mDispatcher->waitForIdle());
4201 mWindow->assertNoEvents();
4202}
4203
4204/**
4205 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
4206 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
4207 * If we process 1 of the events, but ANR on the second event with the same timestamp,
4208 * the ANR mechanism should still work.
4209 *
4210 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
4211 * DOWN event, while not responding on the second one.
4212 */
4213TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
4214 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
4215 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4216 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
4217 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
4218 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004219 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004220
4221 // Now send ACTION_UP, with identical timestamp
4222 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4223 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
4224 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
4225 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004226 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004227
4228 // We have now sent down and up. Let's consume first event and then ANR on the second.
4229 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4230 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004231 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004232}
4233
4234// If an app is not responding to a key event, gesture monitors should continue to receive
4235// new motion events
4236TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
4237 FakeMonitorReceiver monitor =
4238 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
4239 true /*isGestureMonitor*/);
4240
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004241 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4242 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004243 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004245
4246 // Stuck on the ACTION_UP
4247 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004248 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004249
4250 // New tap will go to the gesture monitor, but not to the window
4251 tapOnWindow();
4252 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4253 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
4254
4255 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
4256 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004257 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004258 mWindow->assertNoEvents();
4259 monitor.assertNoEvents();
4260}
4261
4262// If an app is not responding to a motion event, gesture monitors should continue to receive
4263// new motion events
4264TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
4265 FakeMonitorReceiver monitor =
4266 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
4267 true /*isGestureMonitor*/);
4268
4269 tapOnWindow();
4270 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4271 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
4272
4273 mWindow->consumeMotionDown();
4274 // Stuck on the ACTION_UP
4275 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004276 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004277
4278 // New tap will go to the gesture monitor, but not to the window
4279 tapOnWindow();
4280 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4281 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
4282
4283 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
4284 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004285 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004286 mWindow->assertNoEvents();
4287 monitor.assertNoEvents();
4288}
4289
4290// If a window is unresponsive, then you get anr. if the window later catches up and starts to
4291// process events, you don't get an anr. When the window later becomes unresponsive again, you
4292// get an ANR again.
4293// 1. tap -> block on ACTION_UP -> receive ANR
4294// 2. consume all pending events (= queue becomes healthy again)
4295// 3. tap again -> block on ACTION_UP again -> receive ANR second time
4296TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
4297 tapOnWindow();
4298
4299 mWindow->consumeMotionDown();
4300 // Block on ACTION_UP
4301 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004302 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004303 mWindow->consumeMotionUp(); // Now the connection should be healthy again
4304 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004305 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004306 mWindow->assertNoEvents();
4307
4308 tapOnWindow();
4309 mWindow->consumeMotionDown();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004310 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004311 mWindow->consumeMotionUp();
4312
4313 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004314 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004315 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004316 mWindow->assertNoEvents();
4317}
4318
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004319// If a connection remains unresponsive for a while, make sure policy is only notified once about
4320// it.
4321TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004322 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004323 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4324 WINDOW_LOCATION));
4325
4326 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004327 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004328 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004329 // 'notifyConnectionUnresponsive' should only be called once per connection
4330 mFakePolicy->assertNotifyAnrWasNotCalled();
4331 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004332 mWindow->consumeMotionDown();
4333 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
4334 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4335 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004336 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004337 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004338 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004339}
4340
4341/**
4342 * If a window is processing a motion event, and then a key event comes in, the key event should
4343 * not to to the focused window until the motion is processed.
4344 *
4345 * Warning!!!
4346 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
4347 * and the injection timeout that we specify when injecting the key.
4348 * We must have the injection timeout (10ms) be smaller than
4349 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
4350 *
4351 * If that value changes, this test should also change.
4352 */
4353TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
4354 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
4355 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4356
4357 tapOnWindow();
4358 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
4359 ASSERT_TRUE(downSequenceNum);
4360 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
4361 ASSERT_TRUE(upSequenceNum);
4362 // Don't finish the events yet, and send a key
4363 // Injection will "succeed" because we will eventually give up and send the key to the focused
4364 // window even if motions are still being processed. But because the injection timeout is short,
4365 // we will receive INJECTION_TIMED_OUT as the result.
4366
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004367 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004368 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004369 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
4370 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004371 // Key will not be sent to the window, yet, because the window is still processing events
4372 // and the key remains pending, waiting for the touch events to be processed
4373 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
4374 ASSERT_FALSE(keySequenceNum);
4375
4376 std::this_thread::sleep_for(500ms);
4377 // if we wait long enough though, dispatcher will give up, and still send the key
4378 // to the focused window, even though we have not yet finished the motion event
4379 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4380 mWindow->finishEvent(*downSequenceNum);
4381 mWindow->finishEvent(*upSequenceNum);
4382}
4383
4384/**
4385 * If a window is processing a motion event, and then a key event comes in, the key event should
4386 * not go to the focused window until the motion is processed.
4387 * If then a new motion comes in, then the pending key event should be going to the currently
4388 * focused window right away.
4389 */
4390TEST_F(InputDispatcherSingleWindowAnr,
4391 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
4392 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
4393 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4394
4395 tapOnWindow();
4396 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
4397 ASSERT_TRUE(downSequenceNum);
4398 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
4399 ASSERT_TRUE(upSequenceNum);
4400 // Don't finish the events yet, and send a key
4401 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004403 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004404 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004405 // At this point, key is still pending, and should not be sent to the application yet.
4406 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
4407 ASSERT_FALSE(keySequenceNum);
4408
4409 // Now tap down again. It should cause the pending key to go to the focused window right away.
4410 tapOnWindow();
4411 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
4412 // the other events yet. We can finish events in any order.
4413 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
4414 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
4415 mWindow->consumeMotionDown();
4416 mWindow->consumeMotionUp();
4417 mWindow->assertNoEvents();
4418}
4419
4420class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
4421 virtual void SetUp() override {
4422 InputDispatcherTest::SetUp();
4423
Chris Yea209fde2020-07-22 13:54:51 -07004424 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004425 mApplication->setDispatchingTimeout(10ms);
4426 mUnfocusedWindow =
4427 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
4428 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
4429 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
4430 // window.
4431 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
chaviw3277faf2021-05-19 16:45:23 -05004432 mUnfocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL |
4433 WindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
4434 WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004435
4436 mFocusedWindow =
4437 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05004438 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004439 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05004440 mFocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004441
4442 // Set focused application.
4443 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07004444 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004445
4446 // Expect one focus window exist in display.
4447 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004448 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004449 mFocusedWindow->consumeFocusEvent(true);
4450 }
4451
4452 virtual void TearDown() override {
4453 InputDispatcherTest::TearDown();
4454
4455 mUnfocusedWindow.clear();
4456 mFocusedWindow.clear();
4457 }
4458
4459protected:
Chris Yea209fde2020-07-22 13:54:51 -07004460 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004461 sp<FakeWindowHandle> mUnfocusedWindow;
4462 sp<FakeWindowHandle> mFocusedWindow;
4463 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
4464 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
4465 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
4466
4467 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
4468
4469 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
4470
4471private:
4472 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004473 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004474 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4475 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004476 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004477 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4478 location));
4479 }
4480};
4481
4482// If we have 2 windows that are both unresponsive, the one with the shortest timeout
4483// should be ANR'd first.
4484TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004485 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004486 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4487 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004488 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004489 mFocusedWindow->consumeMotionDown();
4490 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4491 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4492 // We consumed all events, so no ANR
4493 ASSERT_TRUE(mDispatcher->waitForIdle());
4494 mFakePolicy->assertNotifyAnrWasNotCalled();
4495
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004496 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004497 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4498 FOCUSED_WINDOW_LOCATION));
4499 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
4500 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004501
4502 const std::chrono::duration timeout =
4503 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004504 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004505 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
4506 // sequence to make it consistent
4507 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004508 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004509 mFocusedWindow->consumeMotionDown();
4510 // This cancel is generated because the connection was unresponsive
4511 mFocusedWindow->consumeMotionCancel();
4512 mFocusedWindow->assertNoEvents();
4513 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004514 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004515 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004516 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004517}
4518
4519// If we have 2 windows with identical timeouts that are both unresponsive,
4520// it doesn't matter which order they should have ANR.
4521// But we should receive ANR for both.
4522TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
4523 // Set the timeout for unfocused window to match the focused window
4524 mUnfocusedWindow->setDispatchingTimeout(10ms);
4525 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
4526
4527 tapOnFocusedWindow();
4528 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004529 sp<IBinder> anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms);
4530 sp<IBinder> anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004531
4532 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004533 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
4534 mFocusedWindow->getToken() == anrConnectionToken2);
4535 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
4536 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004537
4538 ASSERT_TRUE(mDispatcher->waitForIdle());
4539 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004540
4541 mFocusedWindow->consumeMotionDown();
4542 mFocusedWindow->consumeMotionUp();
4543 mUnfocusedWindow->consumeMotionOutside();
4544
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004545 sp<IBinder> responsiveToken1 = mFakePolicy->getResponsiveWindowToken();
4546 sp<IBinder> responsiveToken2 = mFakePolicy->getResponsiveWindowToken();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004547
4548 // Both applications should be marked as responsive, in any order
4549 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
4550 mFocusedWindow->getToken() == responsiveToken2);
4551 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
4552 mUnfocusedWindow->getToken() == responsiveToken2);
4553 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004554}
4555
4556// If a window is already not responding, the second tap on the same window should be ignored.
4557// We should also log an error to account for the dropped event (not tested here).
4558// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
4559TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
4560 tapOnFocusedWindow();
4561 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4562 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4563 // Receive the events, but don't respond
4564 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
4565 ASSERT_TRUE(downEventSequenceNum);
4566 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
4567 ASSERT_TRUE(upEventSequenceNum);
4568 const std::chrono::duration timeout =
4569 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004570 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004571
4572 // Tap once again
4573 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004574 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004575 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4576 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004577 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004578 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4579 FOCUSED_WINDOW_LOCATION));
4580 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
4581 // valid touch target
4582 mUnfocusedWindow->assertNoEvents();
4583
4584 // Consume the first tap
4585 mFocusedWindow->finishEvent(*downEventSequenceNum);
4586 mFocusedWindow->finishEvent(*upEventSequenceNum);
4587 ASSERT_TRUE(mDispatcher->waitForIdle());
4588 // The second tap did not go to the focused window
4589 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004590 // Since all events are finished, connection should be deemed healthy again
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004591 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004592 mFakePolicy->assertNotifyAnrWasNotCalled();
4593}
4594
4595// If you tap outside of all windows, there will not be ANR
4596TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004597 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004598 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4599 LOCATION_OUTSIDE_ALL_WINDOWS));
4600 ASSERT_TRUE(mDispatcher->waitForIdle());
4601 mFakePolicy->assertNotifyAnrWasNotCalled();
4602}
4603
4604// Since the focused window is paused, tapping on it should not produce any events
4605TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
4606 mFocusedWindow->setPaused(true);
4607 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
4608
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004609 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004610 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4611 FOCUSED_WINDOW_LOCATION));
4612
4613 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
4614 ASSERT_TRUE(mDispatcher->waitForIdle());
4615 // Should not ANR because the window is paused, and touches shouldn't go to it
4616 mFakePolicy->assertNotifyAnrWasNotCalled();
4617
4618 mFocusedWindow->assertNoEvents();
4619 mUnfocusedWindow->assertNoEvents();
4620}
4621
4622/**
4623 * If a window is processing a motion event, and then a key event comes in, the key event should
4624 * not to to the focused window until the motion is processed.
4625 * If a different window becomes focused at this time, the key should go to that window instead.
4626 *
4627 * Warning!!!
4628 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
4629 * and the injection timeout that we specify when injecting the key.
4630 * We must have the injection timeout (10ms) be smaller than
4631 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
4632 *
4633 * If that value changes, this test should also change.
4634 */
4635TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
4636 // Set a long ANR timeout to prevent it from triggering
4637 mFocusedWindow->setDispatchingTimeout(2s);
4638 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
4639
4640 tapOnUnfocusedWindow();
4641 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
4642 ASSERT_TRUE(downSequenceNum);
4643 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
4644 ASSERT_TRUE(upSequenceNum);
4645 // Don't finish the events yet, and send a key
4646 // Injection will succeed because we will eventually give up and send the key to the focused
4647 // window even if motions are still being processed.
4648
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004649 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004650 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004651 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
4652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004653 // Key will not be sent to the window, yet, because the window is still processing events
4654 // and the key remains pending, waiting for the touch events to be processed
4655 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
4656 ASSERT_FALSE(keySequenceNum);
4657
4658 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07004659 mFocusedWindow->setFocusable(false);
4660 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004661 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004662 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004663
4664 // Focus events should precede the key events
4665 mUnfocusedWindow->consumeFocusEvent(true);
4666 mFocusedWindow->consumeFocusEvent(false);
4667
4668 // Finish the tap events, which should unblock dispatcher
4669 mUnfocusedWindow->finishEvent(*downSequenceNum);
4670 mUnfocusedWindow->finishEvent(*upSequenceNum);
4671
4672 // Now that all queues are cleared and no backlog in the connections, the key event
4673 // can finally go to the newly focused "mUnfocusedWindow".
4674 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4675 mFocusedWindow->assertNoEvents();
4676 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004677 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004678}
4679
4680// When the touch stream is split across 2 windows, and one of them does not respond,
4681// then ANR should be raised and the touch should be canceled for the unresponsive window.
4682// The other window should not be affected by that.
4683TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
4684 // Touch Window 1
4685 NotifyMotionArgs motionArgs =
4686 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4687 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
4688 mDispatcher->notifyMotion(&motionArgs);
4689 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4690 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4691
4692 // Touch Window 2
4693 int32_t actionPointerDown =
4694 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
4695
4696 motionArgs =
4697 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4698 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
4699 mDispatcher->notifyMotion(&motionArgs);
4700
4701 const std::chrono::duration timeout =
4702 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004703 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004704
4705 mUnfocusedWindow->consumeMotionDown();
4706 mFocusedWindow->consumeMotionDown();
4707 // Focused window may or may not receive ACTION_MOVE
4708 // But it should definitely receive ACTION_CANCEL due to the ANR
4709 InputEvent* event;
4710 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
4711 ASSERT_TRUE(moveOrCancelSequenceNum);
4712 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
4713 ASSERT_NE(nullptr, event);
4714 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
4715 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
4716 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
4717 mFocusedWindow->consumeMotionCancel();
4718 } else {
4719 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
4720 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004721 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004722 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004723
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004724 mUnfocusedWindow->assertNoEvents();
4725 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004726 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004727}
4728
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05004729/**
4730 * If we have no focused window, and a key comes in, we start the ANR timer.
4731 * The focused application should add a focused window before the timer runs out to prevent ANR.
4732 *
4733 * If the user touches another application during this time, the key should be dropped.
4734 * Next, if a new focused window comes in, without toggling the focused application,
4735 * then no ANR should occur.
4736 *
4737 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
4738 * but in some cases the policy may not update the focused application.
4739 */
4740TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
4741 std::shared_ptr<FakeApplicationHandle> focusedApplication =
4742 std::make_shared<FakeApplicationHandle>();
4743 focusedApplication->setDispatchingTimeout(60ms);
4744 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
4745 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
4746 mFocusedWindow->setFocusable(false);
4747
4748 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
4749 mFocusedWindow->consumeFocusEvent(false);
4750
4751 // Send a key. The ANR timer should start because there is no focused window.
4752 // 'focusedApplication' will get blamed if this timer completes.
4753 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004754 InputEventInjectionResult result =
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05004755 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004756 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
4757 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05004759
4760 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
4761 // then the injected touches won't cause the focused event to get dropped.
4762 // The dispatcher only checks for whether the queue should be pruned upon queueing.
4763 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
4764 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
4765 // For this test, it means that the key would get delivered to the window once it becomes
4766 // focused.
4767 std::this_thread::sleep_for(10ms);
4768
4769 // Touch unfocused window. This should force the pending key to get dropped.
4770 NotifyMotionArgs motionArgs =
4771 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4772 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
4773 mDispatcher->notifyMotion(&motionArgs);
4774
4775 // We do not consume the motion right away, because that would require dispatcher to first
4776 // process (== drop) the key event, and by that time, ANR will be raised.
4777 // Set the focused window first.
4778 mFocusedWindow->setFocusable(true);
4779 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
4780 setFocusedWindow(mFocusedWindow);
4781 mFocusedWindow->consumeFocusEvent(true);
4782 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
4783 // to another application. This could be a bug / behaviour in the policy.
4784
4785 mUnfocusedWindow->consumeMotionDown();
4786
4787 ASSERT_TRUE(mDispatcher->waitForIdle());
4788 // Should not ANR because we actually have a focused window. It was just added too slowly.
4789 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
4790}
4791
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05004792// These tests ensure we cannot send touch events to a window that's positioned behind a window
4793// that has feature NO_INPUT_CHANNEL.
4794// Layout:
4795// Top (closest to user)
4796// mNoInputWindow (above all windows)
4797// mBottomWindow
4798// Bottom (furthest from user)
4799class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
4800 virtual void SetUp() override {
4801 InputDispatcherTest::SetUp();
4802
4803 mApplication = std::make_shared<FakeApplicationHandle>();
4804 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
4805 "Window without input channel", ADISPLAY_ID_DEFAULT,
4806 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
4807
chaviw3277faf2021-05-19 16:45:23 -05004808 mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05004809 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
4810 // It's perfectly valid for this window to not have an associated input channel
4811
4812 mBottomWindow = new FakeWindowHandle(mApplication, mDispatcher, "Bottom window",
4813 ADISPLAY_ID_DEFAULT);
4814 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
4815
4816 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
4817 }
4818
4819protected:
4820 std::shared_ptr<FakeApplicationHandle> mApplication;
4821 sp<FakeWindowHandle> mNoInputWindow;
4822 sp<FakeWindowHandle> mBottomWindow;
4823};
4824
4825TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
4826 PointF touchedPoint = {10, 10};
4827
4828 NotifyMotionArgs motionArgs =
4829 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4830 ADISPLAY_ID_DEFAULT, {touchedPoint});
4831 mDispatcher->notifyMotion(&motionArgs);
4832
4833 mNoInputWindow->assertNoEvents();
4834 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
4835 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
4836 // and therefore should prevent mBottomWindow from receiving touches
4837 mBottomWindow->assertNoEvents();
4838}
4839
4840/**
4841 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
4842 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
4843 */
4844TEST_F(InputDispatcherMultiWindowOcclusionTests,
4845 NoInputChannelFeature_DropsTouchesWithValidChannel) {
4846 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
4847 "Window with input channel and NO_INPUT_CHANNEL",
4848 ADISPLAY_ID_DEFAULT);
4849
chaviw3277faf2021-05-19 16:45:23 -05004850 mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05004851 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
4852 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
4853
4854 PointF touchedPoint = {10, 10};
4855
4856 NotifyMotionArgs motionArgs =
4857 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4858 ADISPLAY_ID_DEFAULT, {touchedPoint});
4859 mDispatcher->notifyMotion(&motionArgs);
4860
4861 mNoInputWindow->assertNoEvents();
4862 mBottomWindow->assertNoEvents();
4863}
4864
Vishnu Nair958da932020-08-21 17:12:37 -07004865class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
4866protected:
4867 std::shared_ptr<FakeApplicationHandle> mApp;
4868 sp<FakeWindowHandle> mWindow;
4869 sp<FakeWindowHandle> mMirror;
4870
4871 virtual void SetUp() override {
4872 InputDispatcherTest::SetUp();
4873 mApp = std::make_shared<FakeApplicationHandle>();
4874 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
4875 mMirror = new FakeWindowHandle(mApp, mDispatcher, "TestWindowMirror", ADISPLAY_ID_DEFAULT,
4876 mWindow->getToken());
4877 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
4878 mWindow->setFocusable(true);
4879 mMirror->setFocusable(true);
4880 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4881 }
4882};
4883
4884TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
4885 // Request focus on a mirrored window
4886 setFocusedWindow(mMirror);
4887
4888 // window gets focused
4889 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4891 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004892 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
4893}
4894
4895// A focused & mirrored window remains focused only if the window and its mirror are both
4896// focusable.
4897TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
4898 setFocusedWindow(mMirror);
4899
4900 // window gets focused
4901 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4903 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004904 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4906 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004907 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4908
4909 mMirror->setFocusable(false);
4910 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4911
4912 // window loses focus since one of the windows associated with the token in not focusable
4913 mWindow->consumeFocusEvent(false);
4914
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004915 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4916 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004917 mWindow->assertNoEvents();
4918}
4919
4920// A focused & mirrored window remains focused until the window and its mirror both become
4921// invisible.
4922TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
4923 setFocusedWindow(mMirror);
4924
4925 // window gets focused
4926 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4928 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004929 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004930 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4931 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004932 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4933
4934 mMirror->setVisible(false);
4935 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4936
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4938 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004939 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4941 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004942 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4943
4944 mWindow->setVisible(false);
4945 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4946
4947 // window loses focus only after all windows associated with the token become invisible.
4948 mWindow->consumeFocusEvent(false);
4949
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004950 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4951 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004952 mWindow->assertNoEvents();
4953}
4954
4955// A focused & mirrored window remains focused until both windows are removed.
4956TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
4957 setFocusedWindow(mMirror);
4958
4959 // window gets focused
4960 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4962 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004963 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004964 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4965 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004966 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4967
4968 // single window is removed but the window token remains focused
4969 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
4970
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4972 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004973 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4975 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004976 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4977
4978 // Both windows are removed
4979 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
4980 mWindow->consumeFocusEvent(false);
4981
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004982 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4983 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004984 mWindow->assertNoEvents();
4985}
4986
4987// Focus request can be pending until one window becomes visible.
4988TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
4989 // Request focus on an invisible mirror.
4990 mWindow->setVisible(false);
4991 mMirror->setVisible(false);
4992 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4993 setFocusedWindow(mMirror);
4994
4995 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004996 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07004997 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004998 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07004999
5000 mMirror->setVisible(true);
5001 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5002
5003 // window gets focused
5004 mWindow->consumeFocusEvent(true);
5005 // window gets the pending key event
5006 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5007}
Prabir Pradhan99987712020-11-10 18:43:05 -08005008
5009class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
5010protected:
5011 std::shared_ptr<FakeApplicationHandle> mApp;
5012 sp<FakeWindowHandle> mWindow;
5013 sp<FakeWindowHandle> mSecondWindow;
5014
5015 void SetUp() override {
5016 InputDispatcherTest::SetUp();
5017 mApp = std::make_shared<FakeApplicationHandle>();
5018 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
5019 mWindow->setFocusable(true);
5020 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
5021 mSecondWindow->setFocusable(true);
5022
5023 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5024 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
5025
5026 setFocusedWindow(mWindow);
5027 mWindow->consumeFocusEvent(true);
5028 }
5029
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005030 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
5031 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005032 mDispatcher->notifyPointerCaptureChanged(&args);
5033 }
5034
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005035 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
5036 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08005037 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005038 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
5039 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005040 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005041 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08005042 }
5043};
5044
5045TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
5046 // Ensure that capture cannot be obtained for unfocused windows.
5047 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
5048 mFakePolicy->assertSetPointerCaptureNotCalled();
5049 mSecondWindow->assertNoEvents();
5050
5051 // Ensure that capture can be enabled from the focus window.
5052 requestAndVerifyPointerCapture(mWindow, true);
5053
5054 // Ensure that capture cannot be disabled from a window that does not have capture.
5055 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
5056 mFakePolicy->assertSetPointerCaptureNotCalled();
5057
5058 // Ensure that capture can be disabled from the window with capture.
5059 requestAndVerifyPointerCapture(mWindow, false);
5060}
5061
5062TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005063 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08005064
5065 setFocusedWindow(mSecondWindow);
5066
5067 // Ensure that the capture disabled event was sent first.
5068 mWindow->consumeCaptureEvent(false);
5069 mWindow->consumeFocusEvent(false);
5070 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005071 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08005072
5073 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005074 notifyPointerCaptureChanged({});
5075 notifyPointerCaptureChanged(request);
5076 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08005077 mWindow->assertNoEvents();
5078 mSecondWindow->assertNoEvents();
5079 mFakePolicy->assertSetPointerCaptureNotCalled();
5080}
5081
5082TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005083 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08005084
5085 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005086 notifyPointerCaptureChanged({});
5087 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005088
5089 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005090 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08005091 mWindow->consumeCaptureEvent(false);
5092 mWindow->assertNoEvents();
5093}
5094
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005095TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
5096 requestAndVerifyPointerCapture(mWindow, true);
5097
5098 // The first window loses focus.
5099 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005100 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005101 mWindow->consumeCaptureEvent(false);
5102
5103 // Request Pointer Capture from the second window before the notification from InputReader
5104 // arrives.
5105 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005106 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005107
5108 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005109 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005110
5111 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005112 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005113
5114 mSecondWindow->consumeFocusEvent(true);
5115 mSecondWindow->consumeCaptureEvent(true);
5116}
5117
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005118TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
5119 // App repeatedly enables and disables capture.
5120 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
5121 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
5122 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
5123 mFakePolicy->assertSetPointerCaptureCalled(false);
5124 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
5125 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
5126
5127 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
5128 // first request is now stale, this should do nothing.
5129 notifyPointerCaptureChanged(firstRequest);
5130 mWindow->assertNoEvents();
5131
5132 // InputReader notifies that the second request was enabled.
5133 notifyPointerCaptureChanged(secondRequest);
5134 mWindow->consumeCaptureEvent(true);
5135}
5136
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005137class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
5138protected:
5139 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00005140
5141 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
5142 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
5143
5144 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
5145 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
5146
5147 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
5148 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
5149 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
5150 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
5151 MAXIMUM_OBSCURING_OPACITY);
5152
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005153 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005154 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005155 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005156
5157 sp<FakeWindowHandle> mTouchWindow;
5158
5159 virtual void SetUp() override {
5160 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005161 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005162 mDispatcher->setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode::BLOCK);
5163 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
5164 }
5165
5166 virtual void TearDown() override {
5167 InputDispatcherTest::TearDown();
5168 mTouchWindow.clear();
5169 }
5170
chaviw3277faf2021-05-19 16:45:23 -05005171 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
5172 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005173 sp<FakeWindowHandle> window = getWindow(uid, name);
chaviw3277faf2021-05-19 16:45:23 -05005174 window->setFlags(WindowInfo::Flag::NOT_TOUCHABLE);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005175 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005176 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005177 return window;
5178 }
5179
5180 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
5181 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
5182 sp<FakeWindowHandle> window =
5183 new FakeWindowHandle(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
5184 // Generate an arbitrary PID based on the UID
5185 window->setOwnerInfo(1777 + (uid % 10000), uid);
5186 return window;
5187 }
5188
5189 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
5190 NotifyMotionArgs args =
5191 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5192 ADISPLAY_ID_DEFAULT, points);
5193 mDispatcher->notifyMotion(&args);
5194 }
5195};
5196
5197TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005198 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005199 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005200 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005201
5202 touch();
5203
5204 mTouchWindow->assertNoEvents();
5205}
5206
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005207TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00005208 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
5209 const sp<FakeWindowHandle>& w =
5210 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
5211 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5212
5213 touch();
5214
5215 mTouchWindow->assertNoEvents();
5216}
5217
5218TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005219 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
5220 const sp<FakeWindowHandle>& w =
5221 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
5222 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5223
5224 touch();
5225
5226 w->assertNoEvents();
5227}
5228
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005229TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005230 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
5231 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005232
5233 touch();
5234
5235 mTouchWindow->consumeAnyMotionDown();
5236}
5237
5238TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005239 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005240 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005241 w->setFrame(Rect(0, 0, 50, 50));
5242 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005243
5244 touch({PointF{100, 100}});
5245
5246 mTouchWindow->consumeAnyMotionDown();
5247}
5248
5249TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005250 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005251 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005252 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5253
5254 touch();
5255
5256 mTouchWindow->consumeAnyMotionDown();
5257}
5258
5259TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
5260 const sp<FakeWindowHandle>& w =
5261 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
5262 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005263
5264 touch();
5265
5266 mTouchWindow->consumeAnyMotionDown();
5267}
5268
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005269TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
5270 const sp<FakeWindowHandle>& w =
5271 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
5272 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5273
5274 touch();
5275
5276 w->assertNoEvents();
5277}
5278
5279/**
5280 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
5281 * inside) while letting them pass-through. Note that even though touch passes through the occluding
5282 * window, the occluding window will still receive ACTION_OUTSIDE event.
5283 */
5284TEST_F(InputDispatcherUntrustedTouchesTest,
5285 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
5286 const sp<FakeWindowHandle>& w =
5287 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
chaviw3277faf2021-05-19 16:45:23 -05005288 w->addFlags(WindowInfo::Flag::WATCH_OUTSIDE_TOUCH);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005289 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5290
5291 touch();
5292
5293 w->consumeMotionOutside();
5294}
5295
5296TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
5297 const sp<FakeWindowHandle>& w =
5298 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
chaviw3277faf2021-05-19 16:45:23 -05005299 w->addFlags(WindowInfo::Flag::WATCH_OUTSIDE_TOUCH);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005300 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5301
5302 touch();
5303
5304 InputEvent* event = w->consume();
5305 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
5306 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
5307 EXPECT_EQ(0.0f, motionEvent.getRawPointerCoords(0)->getX());
5308 EXPECT_EQ(0.0f, motionEvent.getRawPointerCoords(0)->getY());
5309}
5310
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005311TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005312 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005313 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5314 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005315 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5316
5317 touch();
5318
5319 mTouchWindow->consumeAnyMotionDown();
5320}
5321
5322TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
5323 const sp<FakeWindowHandle>& w =
5324 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5325 MAXIMUM_OBSCURING_OPACITY);
5326 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005327
5328 touch();
5329
5330 mTouchWindow->consumeAnyMotionDown();
5331}
5332
5333TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005334 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005335 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5336 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005337 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5338
5339 touch();
5340
5341 mTouchWindow->assertNoEvents();
5342}
5343
5344TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
5345 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
5346 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005347 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
5348 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005349 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005350 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
5351 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005352 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5353
5354 touch();
5355
5356 mTouchWindow->assertNoEvents();
5357}
5358
5359TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
5360 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
5361 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005362 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
5363 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005364 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005365 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
5366 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005367 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5368
5369 touch();
5370
5371 mTouchWindow->consumeAnyMotionDown();
5372}
5373
5374TEST_F(InputDispatcherUntrustedTouchesTest,
5375 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
5376 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005377 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5378 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005379 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005380 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5381 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005382 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
5383
5384 touch();
5385
5386 mTouchWindow->consumeAnyMotionDown();
5387}
5388
5389TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
5390 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005391 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5392 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005393 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005394 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5395 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005396 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005397
5398 touch();
5399
5400 mTouchWindow->assertNoEvents();
5401}
5402
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005403TEST_F(InputDispatcherUntrustedTouchesTest,
5404 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
5405 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005406 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5407 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005408 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005409 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5410 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005411 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
5412
5413 touch();
5414
5415 mTouchWindow->assertNoEvents();
5416}
5417
5418TEST_F(InputDispatcherUntrustedTouchesTest,
5419 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
5420 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005421 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5422 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005423 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005424 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5425 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005426 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
5427
5428 touch();
5429
5430 mTouchWindow->consumeAnyMotionDown();
5431}
5432
5433TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
5434 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005435 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5436 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005437 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5438
5439 touch();
5440
5441 mTouchWindow->consumeAnyMotionDown();
5442}
5443
5444TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
5445 const sp<FakeWindowHandle>& w =
5446 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
5447 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5448
5449 touch();
5450
5451 mTouchWindow->consumeAnyMotionDown();
5452}
5453
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00005454TEST_F(InputDispatcherUntrustedTouchesTest,
5455 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
5456 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
5457 const sp<FakeWindowHandle>& w =
5458 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
5459 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5460
5461 touch();
5462
5463 mTouchWindow->assertNoEvents();
5464}
5465
5466TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
5467 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
5468 const sp<FakeWindowHandle>& w =
5469 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
5470 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5471
5472 touch();
5473
5474 mTouchWindow->consumeAnyMotionDown();
5475}
5476
5477TEST_F(InputDispatcherUntrustedTouchesTest,
5478 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
5479 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
5480 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005481 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5482 OPACITY_ABOVE_THRESHOLD);
5483 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5484
5485 touch();
5486
5487 mTouchWindow->consumeAnyMotionDown();
5488}
5489
5490TEST_F(InputDispatcherUntrustedTouchesTest,
5491 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
5492 const sp<FakeWindowHandle>& w1 =
5493 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
5494 OPACITY_BELOW_THRESHOLD);
5495 const sp<FakeWindowHandle>& w2 =
5496 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5497 OPACITY_BELOW_THRESHOLD);
5498 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5499
5500 touch();
5501
5502 mTouchWindow->assertNoEvents();
5503}
5504
5505/**
5506 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
5507 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
5508 * (which alone would result in allowing touches) does not affect the blocking behavior.
5509 */
5510TEST_F(InputDispatcherUntrustedTouchesTest,
5511 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
5512 const sp<FakeWindowHandle>& wB =
5513 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
5514 OPACITY_BELOW_THRESHOLD);
5515 const sp<FakeWindowHandle>& wC =
5516 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5517 OPACITY_BELOW_THRESHOLD);
5518 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
5519
5520 touch();
5521
5522 mTouchWindow->assertNoEvents();
5523}
5524
5525/**
5526 * This test is testing that a window from a different UID but with same application token doesn't
5527 * block the touch. Apps can share the application token for close UI collaboration for example.
5528 */
5529TEST_F(InputDispatcherUntrustedTouchesTest,
5530 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
5531 const sp<FakeWindowHandle>& w =
5532 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
5533 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00005534 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5535
5536 touch();
5537
5538 mTouchWindow->consumeAnyMotionDown();
5539}
5540
arthurhungb89ccb02020-12-30 16:19:01 +08005541class InputDispatcherDragTests : public InputDispatcherTest {
5542protected:
5543 std::shared_ptr<FakeApplicationHandle> mApp;
5544 sp<FakeWindowHandle> mWindow;
5545 sp<FakeWindowHandle> mSecondWindow;
5546 sp<FakeWindowHandle> mDragWindow;
5547
5548 void SetUp() override {
5549 InputDispatcherTest::SetUp();
5550 mApp = std::make_shared<FakeApplicationHandle>();
5551 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
5552 mWindow->setFrame(Rect(0, 0, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05005553 mWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
arthurhungb89ccb02020-12-30 16:19:01 +08005554
5555 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
5556 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
chaviw3277faf2021-05-19 16:45:23 -05005557 mSecondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
arthurhungb89ccb02020-12-30 16:19:01 +08005558
5559 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5560 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
5561 }
5562
5563 // Start performing drag, we will create a drag window and transfer touch to it.
5564 void performDrag() {
5565 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5566 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5567 {50, 50}))
5568 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5569
5570 // Window should receive motion event.
5571 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5572
5573 // The drag window covers the entire display
5574 mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
5575 mDispatcher->setInputWindows(
5576 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5577
5578 // Transfer touch focus to the drag window
5579 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
5580 true /* isDragDrop */);
5581 mWindow->consumeMotionCancel();
5582 mDragWindow->consumeMotionDown();
5583 }
arthurhung6d4bed92021-03-17 11:59:33 +08005584
5585 // Start performing drag, we will create a drag window and transfer touch to it.
5586 void performStylusDrag() {
5587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5588 injectMotionEvent(mDispatcher,
5589 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
5590 AINPUT_SOURCE_STYLUS)
5591 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
5592 .pointer(PointerBuilder(0,
5593 AMOTION_EVENT_TOOL_TYPE_STYLUS)
5594 .x(50)
5595 .y(50))
5596 .build()));
5597 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5598
5599 // The drag window covers the entire display
5600 mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
5601 mDispatcher->setInputWindows(
5602 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5603
5604 // Transfer touch focus to the drag window
5605 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
5606 true /* isDragDrop */);
5607 mWindow->consumeMotionCancel();
5608 mDragWindow->consumeMotionDown();
5609 }
arthurhungb89ccb02020-12-30 16:19:01 +08005610};
5611
5612TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
5613 performDrag();
5614
5615 // Move on window.
5616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5617 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5618 ADISPLAY_ID_DEFAULT, {50, 50}))
5619 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5620 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5621 mWindow->consumeDragEvent(false, 50, 50);
5622 mSecondWindow->assertNoEvents();
5623
5624 // Move to another window.
5625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5626 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5627 ADISPLAY_ID_DEFAULT, {150, 50}))
5628 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5629 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5630 mWindow->consumeDragEvent(true, 150, 50);
5631 mSecondWindow->consumeDragEvent(false, 50, 50);
5632
5633 // Move back to original window.
5634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5635 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5636 ADISPLAY_ID_DEFAULT, {50, 50}))
5637 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5638 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5639 mWindow->consumeDragEvent(false, 50, 50);
5640 mSecondWindow->consumeDragEvent(true, -50, 50);
5641
5642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5643 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
5644 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5645 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5646 mWindow->assertNoEvents();
5647 mSecondWindow->assertNoEvents();
5648}
5649
arthurhungf452d0b2021-01-06 00:19:52 +08005650TEST_F(InputDispatcherDragTests, DragAndDrop) {
5651 performDrag();
5652
5653 // Move on window.
5654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5655 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5656 ADISPLAY_ID_DEFAULT, {50, 50}))
5657 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5658 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5659 mWindow->consumeDragEvent(false, 50, 50);
5660 mSecondWindow->assertNoEvents();
5661
5662 // Move to another window.
5663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5664 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5665 ADISPLAY_ID_DEFAULT, {150, 50}))
5666 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5667 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5668 mWindow->consumeDragEvent(true, 150, 50);
5669 mSecondWindow->consumeDragEvent(false, 50, 50);
5670
5671 // drop to another window.
5672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5673 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5674 {150, 50}))
5675 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5676 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5677 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
5678 mWindow->assertNoEvents();
5679 mSecondWindow->assertNoEvents();
5680}
5681
arthurhung6d4bed92021-03-17 11:59:33 +08005682TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
5683 performStylusDrag();
5684
5685 // Move on window and keep button pressed.
5686 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5687 injectMotionEvent(mDispatcher,
5688 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
5689 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
5690 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5691 .x(50)
5692 .y(50))
5693 .build()))
5694 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5695 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5696 mWindow->consumeDragEvent(false, 50, 50);
5697 mSecondWindow->assertNoEvents();
5698
5699 // Move to another window and release button, expect to drop item.
5700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5701 injectMotionEvent(mDispatcher,
5702 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
5703 .buttonState(0)
5704 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5705 .x(150)
5706 .y(50))
5707 .build()))
5708 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5709 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5710 mWindow->assertNoEvents();
5711 mSecondWindow->assertNoEvents();
5712 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
5713
5714 // nothing to the window.
5715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5716 injectMotionEvent(mDispatcher,
5717 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
5718 .buttonState(0)
5719 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5720 .x(150)
5721 .y(50))
5722 .build()))
5723 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5724 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5725 mWindow->assertNoEvents();
5726 mSecondWindow->assertNoEvents();
5727}
5728
Arthur Hung6d0571e2021-04-09 20:18:16 +08005729TEST_F(InputDispatcherDragTests, DragAndDrop_InvalidWindow) {
5730 performDrag();
5731
5732 // Set second window invisible.
5733 mSecondWindow->setVisible(false);
5734 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5735
5736 // Move on window.
5737 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5738 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5739 ADISPLAY_ID_DEFAULT, {50, 50}))
5740 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5741 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5742 mWindow->consumeDragEvent(false, 50, 50);
5743 mSecondWindow->assertNoEvents();
5744
5745 // Move to another window.
5746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5747 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5748 ADISPLAY_ID_DEFAULT, {150, 50}))
5749 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5750 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5751 mWindow->consumeDragEvent(true, 150, 50);
5752 mSecondWindow->assertNoEvents();
5753
5754 // drop to another window.
5755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5756 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5757 {150, 50}))
5758 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5759 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5760 mFakePolicy->assertDropTargetEquals(nullptr);
5761 mWindow->assertNoEvents();
5762 mSecondWindow->assertNoEvents();
5763}
5764
Vishnu Nair062a8672021-09-03 16:07:44 -07005765class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
5766
5767TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
5768 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5769 sp<FakeWindowHandle> window =
5770 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
5771 window->setInputFeatures(WindowInfo::Feature::DROP_INPUT);
5772 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5773 window->setFocusable(true);
5774 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5775 setFocusedWindow(window);
5776 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
5777
5778 // With the flag set, window should not get any input
5779 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
5780 mDispatcher->notifyKey(&keyArgs);
5781 window->assertNoEvents();
5782
5783 NotifyMotionArgs motionArgs =
5784 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5785 ADISPLAY_ID_DEFAULT);
5786 mDispatcher->notifyMotion(&motionArgs);
5787 window->assertNoEvents();
5788
5789 // With the flag cleared, the window should get input
5790 window->setInputFeatures({});
5791 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5792
5793 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
5794 mDispatcher->notifyKey(&keyArgs);
5795 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
5796
5797 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5798 ADISPLAY_ID_DEFAULT);
5799 mDispatcher->notifyMotion(&motionArgs);
5800 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5801 window->assertNoEvents();
5802}
5803
5804TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
5805 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
5806 std::make_shared<FakeApplicationHandle>();
5807 sp<FakeWindowHandle> obscuringWindow =
5808 new FakeWindowHandle(obscuringApplication, mDispatcher, "obscuringWindow",
5809 ADISPLAY_ID_DEFAULT);
5810 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
5811 obscuringWindow->setOwnerInfo(111, 111);
5812 obscuringWindow->setFlags(WindowInfo::Flag::NOT_TOUCHABLE);
5813 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5814 sp<FakeWindowHandle> window =
5815 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
5816 window->setInputFeatures(WindowInfo::Feature::DROP_INPUT_IF_OBSCURED);
5817 window->setOwnerInfo(222, 222);
5818 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5819 window->setFocusable(true);
5820 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
5821 setFocusedWindow(window);
5822 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
5823
5824 // With the flag set, window should not get any input
5825 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
5826 mDispatcher->notifyKey(&keyArgs);
5827 window->assertNoEvents();
5828
5829 NotifyMotionArgs motionArgs =
5830 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5831 ADISPLAY_ID_DEFAULT);
5832 mDispatcher->notifyMotion(&motionArgs);
5833 window->assertNoEvents();
5834
5835 // With the flag cleared, the window should get input
5836 window->setInputFeatures({});
5837 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
5838
5839 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
5840 mDispatcher->notifyKey(&keyArgs);
5841 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
5842
5843 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5844 ADISPLAY_ID_DEFAULT);
5845 mDispatcher->notifyMotion(&motionArgs);
5846 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5847 window->assertNoEvents();
5848}
5849
5850TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
5851 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
5852 std::make_shared<FakeApplicationHandle>();
5853 sp<FakeWindowHandle> obscuringWindow =
5854 new FakeWindowHandle(obscuringApplication, mDispatcher, "obscuringWindow",
5855 ADISPLAY_ID_DEFAULT);
5856 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
5857 obscuringWindow->setOwnerInfo(111, 111);
5858 obscuringWindow->setFlags(WindowInfo::Flag::NOT_TOUCHABLE);
5859 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5860 sp<FakeWindowHandle> window =
5861 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
5862 window->setInputFeatures(WindowInfo::Feature::DROP_INPUT_IF_OBSCURED);
5863 window->setOwnerInfo(222, 222);
5864 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5865 window->setFocusable(true);
5866 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
5867 setFocusedWindow(window);
5868 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
5869
5870 // With the flag set, window should not get any input
5871 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
5872 mDispatcher->notifyKey(&keyArgs);
5873 window->assertNoEvents();
5874
5875 NotifyMotionArgs motionArgs =
5876 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5877 ADISPLAY_ID_DEFAULT);
5878 mDispatcher->notifyMotion(&motionArgs);
5879 window->assertNoEvents();
5880
5881 // When the window is no longer obscured because it went on top, it should get input
5882 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
5883
5884 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
5885 mDispatcher->notifyKey(&keyArgs);
5886 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
5887
5888 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5889 ADISPLAY_ID_DEFAULT);
5890 mDispatcher->notifyMotion(&motionArgs);
5891 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5892 window->assertNoEvents();
5893}
5894
Garfield Tane84e6f92019-08-29 17:28:41 -07005895} // namespace android::inputdispatcher