blob: 42d3e58545fbf81b024ebb67d7cef241b0e3ae41 [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
Arthur Hung72d8dc32020-03-28 00:48:39 +00002804 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002805
2806 NotifyMotionArgs motionArgs =
2807 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2808 ADISPLAY_ID_DEFAULT);
2809 mDispatcher->notifyMotion(&motionArgs);
2810
2811 InputEvent* event = window->consume();
2812 ASSERT_NE(event, nullptr);
2813
2814 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2815 ASSERT_NE(verified, nullptr);
2816 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
2817
2818 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
2819 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
2820 EXPECT_EQ(motionArgs.source, verified->source);
2821 EXPECT_EQ(motionArgs.displayId, verified->displayId);
2822
2823 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
2824
2825 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
2826 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
2827 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
2828 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
2829 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
2830 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
2831 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
2832}
2833
Prabir Pradhan664834b2021-05-20 16:00:42 -07002834TEST_F(InputDispatcherTest, NonPointerMotionEvent_JoystickAndTouchpadNotTransformed) {
yunho.shinf4a80b82020-11-16 21:13:57 +09002835 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2836 sp<FakeWindowHandle> window =
2837 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2838 const std::string name = window->getName();
2839
2840 // Window gets transformed by offset values.
2841 window->setWindowOffset(500.0f, 500.0f);
2842
2843 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2844 window->setFocusable(true);
2845
2846 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2847
2848 // First, we set focused window so that focusedWindowHandle is not null.
2849 setFocusedWindow(window);
2850
2851 // Second, we consume focus event if it is right or wrong according to onFocusChangedLocked.
2852 window->consumeFocusEvent(true);
2853
Prabir Pradhan664834b2021-05-20 16:00:42 -07002854 constexpr const std::array nonTransformedSources = {std::pair(AINPUT_SOURCE_TOUCHPAD,
2855 AMOTION_EVENT_ACTION_DOWN),
2856 std::pair(AINPUT_SOURCE_JOYSTICK,
2857 AMOTION_EVENT_ACTION_MOVE)};
2858 for (const auto& [source, action] : nonTransformedSources) {
2859 const NotifyMotionArgs motionArgs = generateMotionArgs(action, source, ADISPLAY_ID_DEFAULT);
Prabir Pradhanbd527712021-03-09 19:17:09 -08002860 mDispatcher->notifyMotion(&motionArgs);
yunho.shinf4a80b82020-11-16 21:13:57 +09002861
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00002862 MotionEvent* event = window->consumeMotion();
Prabir Pradhanbd527712021-03-09 19:17:09 -08002863 ASSERT_NE(event, nullptr);
yunho.shinf4a80b82020-11-16 21:13:57 +09002864
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00002865 const MotionEvent& motionEvent = *event;
Prabir Pradhan664834b2021-05-20 16:00:42 -07002866 EXPECT_EQ(action, motionEvent.getAction());
Prabir Pradhanbd527712021-03-09 19:17:09 -08002867 EXPECT_EQ(motionArgs.pointerCount, motionEvent.getPointerCount());
yunho.shinf4a80b82020-11-16 21:13:57 +09002868
Prabir Pradhanbd527712021-03-09 19:17:09 -08002869 float expectedX = motionArgs.pointerCoords[0].getX();
2870 float expectedY = motionArgs.pointerCoords[0].getY();
yunho.shinf4a80b82020-11-16 21:13:57 +09002871
Prabir Pradhanbd527712021-03-09 19:17:09 -08002872 // Ensure the axis values from the final motion event are not transformed.
2873 EXPECT_EQ(expectedX, motionEvent.getX(0))
2874 << "expected " << expectedX << " for x coord of " << name.c_str() << ", got "
2875 << motionEvent.getX(0);
2876 EXPECT_EQ(expectedY, motionEvent.getY(0))
2877 << "expected " << expectedY << " for y coord of " << name.c_str() << ", got "
2878 << motionEvent.getY(0);
2879 // Ensure the raw and transformed axis values for the motion event are the same.
2880 EXPECT_EQ(motionEvent.getRawX(0), motionEvent.getX(0))
2881 << "expected raw and transformed X-axis values to be equal";
2882 EXPECT_EQ(motionEvent.getRawY(0), motionEvent.getY(0))
2883 << "expected raw and transformed Y-axis values to be equal";
2884 }
yunho.shinf4a80b82020-11-16 21:13:57 +09002885}
2886
chaviw09c8d2d2020-08-24 15:48:26 -07002887/**
2888 * Ensure that separate calls to sign the same data are generating the same key.
2889 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
2890 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
2891 * tests.
2892 */
2893TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
2894 KeyEvent event = getTestKeyEvent();
2895 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2896
2897 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
2898 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
2899 ASSERT_EQ(hmac1, hmac2);
2900}
2901
2902/**
2903 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
2904 */
2905TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
2906 KeyEvent event = getTestKeyEvent();
2907 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2908 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
2909
2910 verifiedEvent.deviceId += 1;
2911 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2912
2913 verifiedEvent.source += 1;
2914 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2915
2916 verifiedEvent.eventTimeNanos += 1;
2917 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2918
2919 verifiedEvent.displayId += 1;
2920 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2921
2922 verifiedEvent.action += 1;
2923 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2924
2925 verifiedEvent.downTimeNanos += 1;
2926 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2927
2928 verifiedEvent.flags += 1;
2929 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2930
2931 verifiedEvent.keyCode += 1;
2932 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2933
2934 verifiedEvent.scanCode += 1;
2935 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2936
2937 verifiedEvent.metaState += 1;
2938 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2939
2940 verifiedEvent.repeatCount += 1;
2941 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2942}
2943
Vishnu Nair958da932020-08-21 17:12:37 -07002944TEST_F(InputDispatcherTest, SetFocusedWindow) {
2945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2946 sp<FakeWindowHandle> windowTop =
2947 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2948 sp<FakeWindowHandle> windowSecond =
2949 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2950 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2951
2952 // Top window is also focusable but is not granted focus.
2953 windowTop->setFocusable(true);
2954 windowSecond->setFocusable(true);
2955 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2956 setFocusedWindow(windowSecond);
2957
2958 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2960 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002961
2962 // Focused window should receive event.
2963 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2964 windowTop->assertNoEvents();
2965}
2966
2967TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
2968 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2969 sp<FakeWindowHandle> window =
2970 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2971 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2972
2973 window->setFocusable(true);
2974 // Release channel for window is no longer valid.
2975 window->releaseChannel();
2976 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2977 setFocusedWindow(window);
2978
2979 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002980 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2981 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002982
2983 // window channel is invalid, so it should not receive any input event.
2984 window->assertNoEvents();
2985}
2986
2987TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
2988 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2989 sp<FakeWindowHandle> window =
2990 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2991 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2992
2993 // Window is not focusable.
2994 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2995 setFocusedWindow(window);
2996
2997 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002998 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2999 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003000
3001 // window is invalid, so it should not receive any input event.
3002 window->assertNoEvents();
3003}
3004
3005TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
3006 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3007 sp<FakeWindowHandle> windowTop =
3008 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
3009 sp<FakeWindowHandle> windowSecond =
3010 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3011 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3012
3013 windowTop->setFocusable(true);
3014 windowSecond->setFocusable(true);
3015 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3016 setFocusedWindow(windowTop);
3017 windowTop->consumeFocusEvent(true);
3018
3019 setFocusedWindow(windowSecond, windowTop);
3020 windowSecond->consumeFocusEvent(true);
3021 windowTop->consumeFocusEvent(false);
3022
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3024 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003025
3026 // Focused window should receive event.
3027 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
3028}
3029
3030TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
3031 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3032 sp<FakeWindowHandle> windowTop =
3033 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
3034 sp<FakeWindowHandle> windowSecond =
3035 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3036 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3037
3038 windowTop->setFocusable(true);
3039 windowSecond->setFocusable(true);
3040 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3041 setFocusedWindow(windowSecond, windowTop);
3042
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003043 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3044 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003045
3046 // Event should be dropped.
3047 windowTop->assertNoEvents();
3048 windowSecond->assertNoEvents();
3049}
3050
3051TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
3052 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3053 sp<FakeWindowHandle> window =
3054 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3055 sp<FakeWindowHandle> previousFocusedWindow =
3056 new FakeWindowHandle(application, mDispatcher, "previousFocusedWindow",
3057 ADISPLAY_ID_DEFAULT);
3058 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3059
3060 window->setFocusable(true);
3061 previousFocusedWindow->setFocusable(true);
3062 window->setVisible(false);
3063 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
3064 setFocusedWindow(previousFocusedWindow);
3065 previousFocusedWindow->consumeFocusEvent(true);
3066
3067 // Requesting focus on invisible window takes focus from currently focused window.
3068 setFocusedWindow(window);
3069 previousFocusedWindow->consumeFocusEvent(false);
3070
3071 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003072 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07003073 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003074 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07003075
3076 // Window does not get focus event or key down.
3077 window->assertNoEvents();
3078
3079 // Window becomes visible.
3080 window->setVisible(true);
3081 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3082
3083 // Window receives focus event.
3084 window->consumeFocusEvent(true);
3085 // Focused window receives key down.
3086 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3087}
3088
Vishnu Nair599f1412021-06-21 10:39:58 -07003089TEST_F(InputDispatcherTest, DisplayRemoved) {
3090 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3091 sp<FakeWindowHandle> window =
3092 new FakeWindowHandle(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
3093 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3094
3095 // window is granted focus.
3096 window->setFocusable(true);
3097 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3098 setFocusedWindow(window);
3099 window->consumeFocusEvent(true);
3100
3101 // When a display is removed window loses focus.
3102 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
3103 window->consumeFocusEvent(false);
3104}
3105
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003106/**
3107 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
3108 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
3109 * of the 'slipperyEnterWindow'.
3110 *
3111 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
3112 * a way so that the touched location is no longer covered by the top window.
3113 *
3114 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
3115 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
3116 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
3117 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
3118 * with ACTION_DOWN).
3119 * Thus, the touch has been transferred from the top window into the bottom window, because the top
3120 * window moved itself away from the touched location and had Flag::SLIPPERY.
3121 *
3122 * Even though the top window moved away from the touched location, it is still obscuring the bottom
3123 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
3124 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
3125 *
3126 * In this test, we ensure that the event received by the bottom window has
3127 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
3128 */
3129TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
3130 constexpr int32_t SLIPPERY_PID = INJECTOR_PID + 1;
3131 constexpr int32_t SLIPPERY_UID = INJECTOR_UID + 1;
3132
3133 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3134 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3135
3136 sp<FakeWindowHandle> slipperyExitWindow =
3137 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviw3277faf2021-05-19 16:45:23 -05003138 slipperyExitWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SLIPPERY);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003139 // Make sure this one overlaps the bottom window
3140 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
3141 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
3142 // one. Windows with the same owner are not considered to be occluding each other.
3143 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
3144
3145 sp<FakeWindowHandle> slipperyEnterWindow =
3146 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3147 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
3148
3149 mDispatcher->setInputWindows(
3150 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
3151
3152 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
3153 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3154 ADISPLAY_ID_DEFAULT, {{50, 50}});
3155 mDispatcher->notifyMotion(&args);
3156 slipperyExitWindow->consumeMotionDown();
3157 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
3158 mDispatcher->setInputWindows(
3159 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
3160
3161 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3162 ADISPLAY_ID_DEFAULT, {{51, 51}});
3163 mDispatcher->notifyMotion(&args);
3164
3165 slipperyExitWindow->consumeMotionCancel();
3166
3167 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
3168 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
3169}
3170
Garfield Tan1c7bc862020-01-28 13:24:04 -08003171class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
3172protected:
3173 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
3174 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
3175
Chris Yea209fde2020-07-22 13:54:51 -07003176 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003177 sp<FakeWindowHandle> mWindow;
3178
3179 virtual void SetUp() override {
3180 mFakePolicy = new FakeInputDispatcherPolicy();
3181 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07003182 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003183 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
3184 ASSERT_EQ(OK, mDispatcher->start());
3185
3186 setUpWindow();
3187 }
3188
3189 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07003190 mApp = std::make_shared<FakeApplicationHandle>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08003191 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
3192
Vishnu Nair47074b82020-08-14 11:54:47 -07003193 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003194 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003195 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003196 mWindow->consumeFocusEvent(true);
3197 }
3198
Chris Ye2ad95392020-09-01 13:44:44 -07003199 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08003200 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07003201 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003202 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
3203 mDispatcher->notifyKey(&keyArgs);
3204
3205 // Window should receive key down event.
3206 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3207 }
3208
3209 void expectKeyRepeatOnce(int32_t repeatCount) {
3210 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
3211 InputEvent* repeatEvent = mWindow->consume();
3212 ASSERT_NE(nullptr, repeatEvent);
3213
3214 uint32_t eventType = repeatEvent->getType();
3215 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
3216
3217 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
3218 uint32_t eventAction = repeatKeyEvent->getAction();
3219 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
3220 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
3221 }
3222
Chris Ye2ad95392020-09-01 13:44:44 -07003223 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08003224 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07003225 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003226 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
3227 mDispatcher->notifyKey(&keyArgs);
3228
3229 // Window should receive key down event.
3230 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
3231 0 /*expectedFlags*/);
3232 }
3233};
3234
3235TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Chris Ye2ad95392020-09-01 13:44:44 -07003236 sendAndConsumeKeyDown(1 /* deviceId */);
3237 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3238 expectKeyRepeatOnce(repeatCount);
3239 }
3240}
3241
3242TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
3243 sendAndConsumeKeyDown(1 /* deviceId */);
3244 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3245 expectKeyRepeatOnce(repeatCount);
3246 }
3247 sendAndConsumeKeyDown(2 /* deviceId */);
3248 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08003249 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3250 expectKeyRepeatOnce(repeatCount);
3251 }
3252}
3253
3254TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Chris Ye2ad95392020-09-01 13:44:44 -07003255 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003256 expectKeyRepeatOnce(1 /*repeatCount*/);
Chris Ye2ad95392020-09-01 13:44:44 -07003257 sendAndConsumeKeyUp(1 /* deviceId */);
3258 mWindow->assertNoEvents();
3259}
3260
3261TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
3262 sendAndConsumeKeyDown(1 /* deviceId */);
3263 expectKeyRepeatOnce(1 /*repeatCount*/);
3264 sendAndConsumeKeyDown(2 /* deviceId */);
3265 expectKeyRepeatOnce(1 /*repeatCount*/);
3266 // Stale key up from device 1.
3267 sendAndConsumeKeyUp(1 /* deviceId */);
3268 // Device 2 is still down, keep repeating
3269 expectKeyRepeatOnce(2 /*repeatCount*/);
3270 expectKeyRepeatOnce(3 /*repeatCount*/);
3271 // Device 2 key up
3272 sendAndConsumeKeyUp(2 /* deviceId */);
3273 mWindow->assertNoEvents();
3274}
3275
3276TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
3277 sendAndConsumeKeyDown(1 /* deviceId */);
3278 expectKeyRepeatOnce(1 /*repeatCount*/);
3279 sendAndConsumeKeyDown(2 /* deviceId */);
3280 expectKeyRepeatOnce(1 /*repeatCount*/);
3281 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
3282 sendAndConsumeKeyUp(2 /* deviceId */);
3283 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08003284 mWindow->assertNoEvents();
3285}
3286
liushenxiang42232912021-05-21 20:24:09 +08003287TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
3288 sendAndConsumeKeyDown(DEVICE_ID);
3289 expectKeyRepeatOnce(1 /*repeatCount*/);
3290 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
3291 mDispatcher->notifyDeviceReset(&args);
3292 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
3293 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
3294 mWindow->assertNoEvents();
3295}
3296
Garfield Tan1c7bc862020-01-28 13:24:04 -08003297TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Chris Ye2ad95392020-09-01 13:44:44 -07003298 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003299 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3300 InputEvent* repeatEvent = mWindow->consume();
3301 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
3302 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
3303 IdGenerator::getSource(repeatEvent->getId()));
3304 }
3305}
3306
3307TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Chris Ye2ad95392020-09-01 13:44:44 -07003308 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003309
3310 std::unordered_set<int32_t> idSet;
3311 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3312 InputEvent* repeatEvent = mWindow->consume();
3313 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
3314 int32_t id = repeatEvent->getId();
3315 EXPECT_EQ(idSet.end(), idSet.find(id));
3316 idSet.insert(id);
3317 }
3318}
3319
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003320/* Test InputDispatcher for MultiDisplay */
3321class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
3322public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003323 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003324 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08003325
Chris Yea209fde2020-07-22 13:54:51 -07003326 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003327 windowInPrimary =
3328 new FakeWindowHandle(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003329
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003330 // Set focus window for primary display, but focused display would be second one.
3331 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07003332 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003333 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003334 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003335 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08003336
Chris Yea209fde2020-07-22 13:54:51 -07003337 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003338 windowInSecondary =
3339 new FakeWindowHandle(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003340 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003341 // Set focus display to second one.
3342 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
3343 // Set focus window for second display.
3344 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07003345 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003346 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003347 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003348 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003349 }
3350
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003351 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003352 InputDispatcherTest::TearDown();
3353
Chris Yea209fde2020-07-22 13:54:51 -07003354 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003355 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07003356 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003357 windowInSecondary.clear();
3358 }
3359
3360protected:
Chris Yea209fde2020-07-22 13:54:51 -07003361 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003362 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07003363 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003364 sp<FakeWindowHandle> windowInSecondary;
3365};
3366
3367TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
3368 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003369 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3370 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3371 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003372 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08003373 windowInSecondary->assertNoEvents();
3374
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003375 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003376 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3377 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
3378 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08003379 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003380 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08003381}
3382
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003383TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08003384 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003385 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3386 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003387 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003388 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08003389 windowInSecondary->assertNoEvents();
3390
3391 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003393 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08003394 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003395 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08003396
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003397 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00003398 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08003399
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003400 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003401 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
3402 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08003403
3404 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003405 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003406 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08003407 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003408 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08003409 windowInSecondary->assertNoEvents();
3410}
3411
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003412// Test per-display input monitors for motion event.
3413TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08003414 FakeMonitorReceiver monitorInPrimary =
3415 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
3416 FakeMonitorReceiver monitorInSecondary =
3417 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003418
3419 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003420 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3421 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3422 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003423 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08003424 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003425 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003426 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003427
3428 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3430 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
3431 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003432 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003433 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003434 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08003435 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003436
3437 // Test inject a non-pointer motion event.
3438 // If specific a display, it will dispatch to the focused window of particular display,
3439 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003440 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3441 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
3442 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003443 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003444 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003445 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08003446 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003447}
3448
3449// Test per-display input monitors for key event.
3450TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003451 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08003452 FakeMonitorReceiver monitorInPrimary =
3453 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
3454 FakeMonitorReceiver monitorInSecondary =
3455 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003456
3457 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3459 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003460 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003461 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003462 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08003463 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003464}
3465
Vishnu Nair958da932020-08-21 17:12:37 -07003466TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
3467 sp<FakeWindowHandle> secondWindowInPrimary =
3468 new FakeWindowHandle(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
3469 secondWindowInPrimary->setFocusable(true);
3470 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
3471 setFocusedWindow(secondWindowInPrimary);
3472 windowInPrimary->consumeFocusEvent(false);
3473 secondWindowInPrimary->consumeFocusEvent(true);
3474
3475 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003476 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
3477 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003478 windowInPrimary->assertNoEvents();
3479 windowInSecondary->assertNoEvents();
3480 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3481}
3482
Jackal Guof9696682018-10-05 12:23:23 +08003483class InputFilterTest : public InputDispatcherTest {
3484protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07003485 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
3486 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08003487 NotifyMotionArgs motionArgs;
3488
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003489 motionArgs =
3490 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08003491 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003492 motionArgs =
3493 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08003494 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003495 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08003496 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07003497 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
3498 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08003499 } else {
3500 mFakePolicy->assertFilterInputEventWasNotCalled();
3501 }
3502 }
3503
3504 void testNotifyKey(bool expectToBeFiltered) {
3505 NotifyKeyArgs keyArgs;
3506
3507 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
3508 mDispatcher->notifyKey(&keyArgs);
3509 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
3510 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003511 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08003512
3513 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08003514 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08003515 } else {
3516 mFakePolicy->assertFilterInputEventWasNotCalled();
3517 }
3518 }
3519};
3520
3521// Test InputFilter for MotionEvent
3522TEST_F(InputFilterTest, MotionEvent_InputFilter) {
3523 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
3524 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
3525 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
3526
3527 // Enable InputFilter
3528 mDispatcher->setInputFilterEnabled(true);
3529 // Test touch on both primary and second display, and check if both events are filtered.
3530 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
3531 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
3532
3533 // Disable InputFilter
3534 mDispatcher->setInputFilterEnabled(false);
3535 // Test touch on both primary and second display, and check if both events aren't filtered.
3536 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
3537 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
3538}
3539
3540// Test InputFilter for KeyEvent
3541TEST_F(InputFilterTest, KeyEvent_InputFilter) {
3542 // Since the InputFilter is disabled by default, check if key event aren't filtered.
3543 testNotifyKey(/*expectToBeFiltered*/ false);
3544
3545 // Enable InputFilter
3546 mDispatcher->setInputFilterEnabled(true);
3547 // Send a key event, and check if it is filtered.
3548 testNotifyKey(/*expectToBeFiltered*/ true);
3549
3550 // Disable InputFilter
3551 mDispatcher->setInputFilterEnabled(false);
3552 // Send a key event, and check if it isn't filtered.
3553 testNotifyKey(/*expectToBeFiltered*/ false);
3554}
3555
Prabir Pradhan81420cc2021-09-06 10:28:50 -07003556// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
3557// logical display coordinate space.
3558TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
3559 ui::Transform firstDisplayTransform;
3560 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
3561 ui::Transform secondDisplayTransform;
3562 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
3563
3564 std::vector<gui::DisplayInfo> displayInfos(2);
3565 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
3566 displayInfos[0].transform = firstDisplayTransform;
3567 displayInfos[1].displayId = SECOND_DISPLAY_ID;
3568 displayInfos[1].transform = secondDisplayTransform;
3569
3570 mDispatcher->onWindowInfosChanged({}, displayInfos);
3571
3572 // Enable InputFilter
3573 mDispatcher->setInputFilterEnabled(true);
3574
3575 // Ensure the correct transforms are used for the displays.
3576 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
3577 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
3578}
3579
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003580class InputFilterInjectionPolicyTest : public InputDispatcherTest {
3581protected:
3582 virtual void SetUp() override {
3583 InputDispatcherTest::SetUp();
3584
3585 /**
3586 * We don't need to enable input filter to test the injected event policy, but we enabled it
3587 * here to make the tests more realistic, since this policy only matters when inputfilter is
3588 * on.
3589 */
3590 mDispatcher->setInputFilterEnabled(true);
3591
3592 std::shared_ptr<InputApplicationHandle> application =
3593 std::make_shared<FakeApplicationHandle>();
3594 mWindow =
3595 new FakeWindowHandle(application, mDispatcher, "Test Window", ADISPLAY_ID_DEFAULT);
3596
3597 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3598 mWindow->setFocusable(true);
3599 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3600 setFocusedWindow(mWindow);
3601 mWindow->consumeFocusEvent(true);
3602 }
3603
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003604 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
3605 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003606 KeyEvent event;
3607
3608 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3609 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
3610 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
3611 KEY_A, AMETA_NONE, 0 /*repeatCount*/, eventTime, eventTime);
3612 const int32_t additionalPolicyFlags =
3613 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
3614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3615 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
3616 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
3617 policyFlags | additionalPolicyFlags));
3618
3619 InputEvent* received = mWindow->consume();
3620 ASSERT_NE(nullptr, received);
3621 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003622 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_KEY);
3623 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
3624 ASSERT_EQ(flags, keyEvent.getFlags());
3625 }
3626
3627 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
3628 int32_t flags) {
3629 MotionEvent event;
3630 PointerProperties pointerProperties[1];
3631 PointerCoords pointerCoords[1];
3632 pointerProperties[0].clear();
3633 pointerProperties[0].id = 0;
3634 pointerCoords[0].clear();
3635 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
3636 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
3637
3638 ui::Transform identityTransform;
3639 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3640 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
3641 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
3642 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
3643 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07003644 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07003645 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003646 /*pointerCount*/ 1, pointerProperties, pointerCoords);
3647
3648 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
3649 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3650 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
3651 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
3652 policyFlags | additionalPolicyFlags));
3653
3654 InputEvent* received = mWindow->consume();
3655 ASSERT_NE(nullptr, received);
3656 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
3657 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_MOTION);
3658 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
3659 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003660 }
3661
3662private:
3663 sp<FakeWindowHandle> mWindow;
3664};
3665
3666TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003667 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
3668 // filter. Without it, the event will no different from a regularly injected event, and the
3669 // injected device id will be overwritten.
3670 testInjectedKey(POLICY_FLAG_FILTERED, 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3671 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003672}
3673
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003674TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003675 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003676 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3677 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3678}
3679
3680TEST_F(InputFilterInjectionPolicyTest,
3681 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
3682 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
3683 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3684 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003685}
3686
3687TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
3688 testInjectedKey(0 /*policyFlags*/, 3 /*injectedDeviceId*/,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003689 VIRTUAL_KEYBOARD_ID /*resolvedDeviceId*/, 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003690}
3691
chaviwfd6d3512019-03-25 13:23:49 -07003692class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003693 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07003694 InputDispatcherTest::SetUp();
3695
Chris Yea209fde2020-07-22 13:54:51 -07003696 std::shared_ptr<FakeApplicationHandle> application =
3697 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003698 mUnfocusedWindow =
3699 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07003700 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
3701 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3702 // window.
chaviw3277faf2021-05-19 16:45:23 -05003703 mUnfocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07003704
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003705 mFocusedWindow =
3706 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3707 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05003708 mFocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07003709
3710 // Set focused application.
3711 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07003712 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07003713
3714 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00003715 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003716 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003717 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07003718 }
3719
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003720 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07003721 InputDispatcherTest::TearDown();
3722
3723 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003724 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07003725 }
3726
3727protected:
3728 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003729 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003730 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07003731};
3732
3733// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
3734// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
3735// the onPointerDownOutsideFocus callback.
3736TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003737 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003738 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3739 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003740 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003741 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07003742
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003743 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07003744 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
3745}
3746
3747// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
3748// DOWN on the window that doesn't have focus. Ensure no window received the
3749// onPointerDownOutsideFocus callback.
3750TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003752 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003753 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003754 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07003755
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003756 ASSERT_TRUE(mDispatcher->waitForIdle());
3757 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07003758}
3759
3760// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
3761// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
3762TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003763 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3764 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003765 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003766 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07003767
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003768 ASSERT_TRUE(mDispatcher->waitForIdle());
3769 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07003770}
3771
3772// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
3773// DOWN on the window that already has focus. Ensure no window received the
3774// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003775TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003777 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003778 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003779 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003780 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07003781
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003782 ASSERT_TRUE(mDispatcher->waitForIdle());
3783 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07003784}
3785
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08003786// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
3787// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
3788TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
3789 const MotionEvent event =
3790 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3791 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
3792 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(20).y(20))
3793 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
3794 .build();
3795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
3796 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3797 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
3798
3799 ASSERT_TRUE(mDispatcher->waitForIdle());
3800 mFakePolicy->assertOnPointerDownWasNotCalled();
3801 // Ensure that the unfocused window did not receive any FOCUS events.
3802 mUnfocusedWindow->assertNoEvents();
3803}
3804
chaviwaf87b3e2019-10-01 16:59:28 -07003805// These tests ensures we can send touch events to a single client when there are multiple input
3806// windows that point to the same client token.
3807class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
3808 virtual void SetUp() override {
3809 InputDispatcherTest::SetUp();
3810
Chris Yea209fde2020-07-22 13:54:51 -07003811 std::shared_ptr<FakeApplicationHandle> application =
3812 std::make_shared<FakeApplicationHandle>();
chaviwaf87b3e2019-10-01 16:59:28 -07003813 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
3814 ADISPLAY_ID_DEFAULT);
3815 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
3816 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
chaviw3277faf2021-05-19 16:45:23 -05003817 mWindow1->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07003818 mWindow1->setFrame(Rect(0, 0, 100, 100));
3819
3820 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
3821 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviw3277faf2021-05-19 16:45:23 -05003822 mWindow2->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07003823 mWindow2->setFrame(Rect(100, 100, 200, 200));
3824
Arthur Hung72d8dc32020-03-28 00:48:39 +00003825 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07003826 }
3827
3828protected:
3829 sp<FakeWindowHandle> mWindow1;
3830 sp<FakeWindowHandle> mWindow2;
3831
3832 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05003833 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07003834 vec2 vals = windowInfo->transform.transform(point.x, point.y);
3835 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07003836 }
3837
3838 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
3839 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003840 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07003841 InputEvent* event = window->consume();
3842
3843 ASSERT_NE(nullptr, event) << name.c_str()
3844 << ": consumer should have returned non-NULL event.";
3845
3846 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
3847 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
3848 << " event, got " << inputEventTypeToString(event->getType()) << " event";
3849
3850 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003851 assertMotionAction(expectedAction, motionEvent.getAction());
chaviwaf87b3e2019-10-01 16:59:28 -07003852
3853 for (size_t i = 0; i < points.size(); i++) {
3854 float expectedX = points[i].x;
3855 float expectedY = points[i].y;
3856
3857 EXPECT_EQ(expectedX, motionEvent.getX(i))
3858 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
3859 << ", got " << motionEvent.getX(i);
3860 EXPECT_EQ(expectedY, motionEvent.getY(i))
3861 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
3862 << ", got " << motionEvent.getY(i);
3863 }
3864 }
chaviw9eaa22c2020-07-01 16:21:27 -07003865
3866 void touchAndAssertPositions(int32_t action, std::vector<PointF> touchedPoints,
3867 std::vector<PointF> expectedPoints) {
3868 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
3869 ADISPLAY_ID_DEFAULT, touchedPoints);
3870 mDispatcher->notifyMotion(&motionArgs);
3871
3872 // Always consume from window1 since it's the window that has the InputReceiver
3873 consumeMotionEvent(mWindow1, action, expectedPoints);
3874 }
chaviwaf87b3e2019-10-01 16:59:28 -07003875};
3876
3877TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
3878 // Touch Window 1
3879 PointF touchedPoint = {10, 10};
3880 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003881 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003882
3883 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07003884 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003885
3886 // Touch Window 2
3887 touchedPoint = {150, 150};
3888 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003889 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003890}
3891
chaviw9eaa22c2020-07-01 16:21:27 -07003892TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
3893 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07003894 mWindow2->setWindowScale(0.5f, 0.5f);
3895
3896 // Touch Window 1
3897 PointF touchedPoint = {10, 10};
3898 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003899 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003900 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07003901 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003902
3903 // Touch Window 2
3904 touchedPoint = {150, 150};
3905 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003906 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
3907 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003908
chaviw9eaa22c2020-07-01 16:21:27 -07003909 // Update the transform so rotation is set
3910 mWindow2->setWindowTransform(0, -1, 1, 0);
3911 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
3912 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003913}
3914
chaviw9eaa22c2020-07-01 16:21:27 -07003915TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003916 mWindow2->setWindowScale(0.5f, 0.5f);
3917
3918 // Touch Window 1
3919 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3920 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003921 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003922
3923 // Touch Window 2
3924 int32_t actionPointerDown =
3925 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003926 touchedPoints.push_back(PointF{150, 150});
3927 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3928 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003929
chaviw9eaa22c2020-07-01 16:21:27 -07003930 // Release Window 2
3931 int32_t actionPointerUp =
3932 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3933 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
3934 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003935
chaviw9eaa22c2020-07-01 16:21:27 -07003936 // Update the transform so rotation is set for Window 2
3937 mWindow2->setWindowTransform(0, -1, 1, 0);
3938 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3939 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003940}
3941
chaviw9eaa22c2020-07-01 16:21:27 -07003942TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003943 mWindow2->setWindowScale(0.5f, 0.5f);
3944
3945 // Touch Window 1
3946 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3947 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003948 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003949
3950 // Touch Window 2
3951 int32_t actionPointerDown =
3952 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003953 touchedPoints.push_back(PointF{150, 150});
3954 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003955
chaviw9eaa22c2020-07-01 16:21:27 -07003956 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003957
3958 // Move both windows
3959 touchedPoints = {{20, 20}, {175, 175}};
3960 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3961 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3962
chaviw9eaa22c2020-07-01 16:21:27 -07003963 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003964
chaviw9eaa22c2020-07-01 16:21:27 -07003965 // Release Window 2
3966 int32_t actionPointerUp =
3967 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3968 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
3969 expectedPoints.pop_back();
3970
3971 // Touch Window 2
3972 mWindow2->setWindowTransform(0, -1, 1, 0);
3973 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3974 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
3975
3976 // Move both windows
3977 touchedPoints = {{20, 20}, {175, 175}};
3978 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3979 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3980
3981 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003982}
3983
3984TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
3985 mWindow1->setWindowScale(0.5f, 0.5f);
3986
3987 // Touch Window 1
3988 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3989 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003990 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003991
3992 // Touch Window 2
3993 int32_t actionPointerDown =
3994 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003995 touchedPoints.push_back(PointF{150, 150});
3996 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003997
chaviw9eaa22c2020-07-01 16:21:27 -07003998 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003999
4000 // Move both windows
4001 touchedPoints = {{20, 20}, {175, 175}};
4002 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
4003 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
4004
chaviw9eaa22c2020-07-01 16:21:27 -07004005 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004006}
4007
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004008class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
4009 virtual void SetUp() override {
4010 InputDispatcherTest::SetUp();
4011
Chris Yea209fde2020-07-22 13:54:51 -07004012 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004013 mApplication->setDispatchingTimeout(20ms);
4014 mWindow =
4015 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
4016 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05004017 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07004018 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004019 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
4020 // window.
chaviw3277faf2021-05-19 16:45:23 -05004021 mWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004022
4023 // Set focused application.
4024 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
4025
4026 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004027 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004028 mWindow->consumeFocusEvent(true);
4029 }
4030
4031 virtual void TearDown() override {
4032 InputDispatcherTest::TearDown();
4033 mWindow.clear();
4034 }
4035
4036protected:
Chris Yea209fde2020-07-22 13:54:51 -07004037 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004038 sp<FakeWindowHandle> mWindow;
4039 static constexpr PointF WINDOW_LOCATION = {20, 20};
4040
4041 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004042 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004043 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4044 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004045 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004046 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4047 WINDOW_LOCATION));
4048 }
4049};
4050
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004051// Send a tap and respond, which should not cause an ANR.
4052TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
4053 tapOnWindow();
4054 mWindow->consumeMotionDown();
4055 mWindow->consumeMotionUp();
4056 ASSERT_TRUE(mDispatcher->waitForIdle());
4057 mFakePolicy->assertNotifyAnrWasNotCalled();
4058}
4059
4060// Send a regular key and respond, which should not cause an ANR.
4061TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004063 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
4064 ASSERT_TRUE(mDispatcher->waitForIdle());
4065 mFakePolicy->assertNotifyAnrWasNotCalled();
4066}
4067
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004068TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
4069 mWindow->setFocusable(false);
4070 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4071 mWindow->consumeFocusEvent(false);
4072
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004073 InputEventInjectionResult result =
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004074 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004075 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
4076 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004078 // Key will not go to window because we have no focused window.
4079 // The 'no focused window' ANR timer should start instead.
4080
4081 // Now, the focused application goes away.
4082 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
4083 // The key should get dropped and there should be no ANR.
4084
4085 ASSERT_TRUE(mDispatcher->waitForIdle());
4086 mFakePolicy->assertNotifyAnrWasNotCalled();
4087}
4088
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004089// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004090// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
4091// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004092TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004093 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004094 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4095 WINDOW_LOCATION));
4096
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004097 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
4098 ASSERT_TRUE(sequenceNum);
4099 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004100 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004101
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004102 mWindow->finishEvent(*sequenceNum);
4103 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
4104 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004105 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004106 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004107}
4108
4109// Send a key to the app and have the app not respond right away.
4110TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
4111 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004112 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004113 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
4114 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004115 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004116 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004117 ASSERT_TRUE(mDispatcher->waitForIdle());
4118}
4119
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004120// We have a focused application, but no focused window
4121TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004122 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004123 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4124 mWindow->consumeFocusEvent(false);
4125
4126 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004127 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004128 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4129 WINDOW_LOCATION));
4130 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
4131 mDispatcher->waitForIdle();
4132 mFakePolicy->assertNotifyAnrWasNotCalled();
4133
4134 // Once a focused event arrives, we get an ANR for this application
4135 // We specify the injection timeout to be smaller than the application timeout, to ensure that
4136 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004137 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004138 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004139 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004140 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004141 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004142 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004143 ASSERT_TRUE(mDispatcher->waitForIdle());
4144}
4145
4146// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004147// Make sure that we don't notify policy twice about the same ANR.
4148TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004149 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004150 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4151 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004152
4153 // Once a focused event arrives, we get an ANR for this application
4154 // We specify the injection timeout to be smaller than the application timeout, to ensure that
4155 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004156 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004157 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004158 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004159 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004160 const std::chrono::duration appTimeout =
4161 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004162 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004163
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004164 std::this_thread::sleep_for(appTimeout);
4165 // ANR should not be raised again. It is up to policy to do that if it desires.
4166 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004167
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004168 // If we now get a focused window, the ANR should stop, but the policy handles that via
4169 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004170 ASSERT_TRUE(mDispatcher->waitForIdle());
4171}
4172
4173// We have a focused application, but no focused window
4174TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004175 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004176 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4177 mWindow->consumeFocusEvent(false);
4178
4179 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004180 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004181 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004182 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
4183 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004184
4185 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004186 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004187
4188 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004189 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004190 ASSERT_TRUE(mDispatcher->waitForIdle());
4191 mWindow->assertNoEvents();
4192}
4193
4194/**
4195 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
4196 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
4197 * If we process 1 of the events, but ANR on the second event with the same timestamp,
4198 * the ANR mechanism should still work.
4199 *
4200 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
4201 * DOWN event, while not responding on the second one.
4202 */
4203TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
4204 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
4205 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4206 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
4207 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
4208 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004209 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004210
4211 // Now send ACTION_UP, with identical timestamp
4212 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4213 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
4214 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
4215 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004216 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004217
4218 // We have now sent down and up. Let's consume first event and then ANR on the second.
4219 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4220 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004221 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004222}
4223
4224// If an app is not responding to a key event, gesture monitors should continue to receive
4225// new motion events
4226TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
4227 FakeMonitorReceiver monitor =
4228 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
4229 true /*isGestureMonitor*/);
4230
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004231 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4232 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004233 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004235
4236 // Stuck on the ACTION_UP
4237 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004238 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004239
4240 // New tap will go to the gesture monitor, but not to the window
4241 tapOnWindow();
4242 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4243 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
4244
4245 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
4246 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004247 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004248 mWindow->assertNoEvents();
4249 monitor.assertNoEvents();
4250}
4251
4252// If an app is not responding to a motion event, gesture monitors should continue to receive
4253// new motion events
4254TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
4255 FakeMonitorReceiver monitor =
4256 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
4257 true /*isGestureMonitor*/);
4258
4259 tapOnWindow();
4260 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4261 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
4262
4263 mWindow->consumeMotionDown();
4264 // Stuck on the ACTION_UP
4265 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004266 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004267
4268 // New tap will go to the gesture monitor, but not to the window
4269 tapOnWindow();
4270 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4271 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
4272
4273 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
4274 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004275 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004276 mWindow->assertNoEvents();
4277 monitor.assertNoEvents();
4278}
4279
4280// If a window is unresponsive, then you get anr. if the window later catches up and starts to
4281// process events, you don't get an anr. When the window later becomes unresponsive again, you
4282// get an ANR again.
4283// 1. tap -> block on ACTION_UP -> receive ANR
4284// 2. consume all pending events (= queue becomes healthy again)
4285// 3. tap again -> block on ACTION_UP again -> receive ANR second time
4286TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
4287 tapOnWindow();
4288
4289 mWindow->consumeMotionDown();
4290 // Block on ACTION_UP
4291 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004292 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004293 mWindow->consumeMotionUp(); // Now the connection should be healthy again
4294 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004295 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004296 mWindow->assertNoEvents();
4297
4298 tapOnWindow();
4299 mWindow->consumeMotionDown();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004300 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004301 mWindow->consumeMotionUp();
4302
4303 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004304 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004305 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004306 mWindow->assertNoEvents();
4307}
4308
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004309// If a connection remains unresponsive for a while, make sure policy is only notified once about
4310// it.
4311TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004312 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004313 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4314 WINDOW_LOCATION));
4315
4316 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004317 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004318 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004319 // 'notifyConnectionUnresponsive' should only be called once per connection
4320 mFakePolicy->assertNotifyAnrWasNotCalled();
4321 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004322 mWindow->consumeMotionDown();
4323 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
4324 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4325 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004326 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004327 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004328 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004329}
4330
4331/**
4332 * If a window is processing a motion event, and then a key event comes in, the key event should
4333 * not to to the focused window until the motion is processed.
4334 *
4335 * Warning!!!
4336 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
4337 * and the injection timeout that we specify when injecting the key.
4338 * We must have the injection timeout (10ms) be smaller than
4339 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
4340 *
4341 * If that value changes, this test should also change.
4342 */
4343TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
4344 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
4345 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4346
4347 tapOnWindow();
4348 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
4349 ASSERT_TRUE(downSequenceNum);
4350 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
4351 ASSERT_TRUE(upSequenceNum);
4352 // Don't finish the events yet, and send a key
4353 // Injection will "succeed" because we will eventually give up and send the key to the focused
4354 // window even if motions are still being processed. But because the injection timeout is short,
4355 // we will receive INJECTION_TIMED_OUT as the result.
4356
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004357 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004358 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004359 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
4360 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004361 // Key will not be sent to the window, yet, because the window is still processing events
4362 // and the key remains pending, waiting for the touch events to be processed
4363 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
4364 ASSERT_FALSE(keySequenceNum);
4365
4366 std::this_thread::sleep_for(500ms);
4367 // if we wait long enough though, dispatcher will give up, and still send the key
4368 // to the focused window, even though we have not yet finished the motion event
4369 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4370 mWindow->finishEvent(*downSequenceNum);
4371 mWindow->finishEvent(*upSequenceNum);
4372}
4373
4374/**
4375 * If a window is processing a motion event, and then a key event comes in, the key event should
4376 * not go to the focused window until the motion is processed.
4377 * If then a new motion comes in, then the pending key event should be going to the currently
4378 * focused window right away.
4379 */
4380TEST_F(InputDispatcherSingleWindowAnr,
4381 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
4382 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
4383 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4384
4385 tapOnWindow();
4386 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
4387 ASSERT_TRUE(downSequenceNum);
4388 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
4389 ASSERT_TRUE(upSequenceNum);
4390 // Don't finish the events yet, and send a key
4391 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004393 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004394 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004395 // At this point, key is still pending, and should not be sent to the application yet.
4396 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
4397 ASSERT_FALSE(keySequenceNum);
4398
4399 // Now tap down again. It should cause the pending key to go to the focused window right away.
4400 tapOnWindow();
4401 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
4402 // the other events yet. We can finish events in any order.
4403 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
4404 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
4405 mWindow->consumeMotionDown();
4406 mWindow->consumeMotionUp();
4407 mWindow->assertNoEvents();
4408}
4409
4410class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
4411 virtual void SetUp() override {
4412 InputDispatcherTest::SetUp();
4413
Chris Yea209fde2020-07-22 13:54:51 -07004414 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004415 mApplication->setDispatchingTimeout(10ms);
4416 mUnfocusedWindow =
4417 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
4418 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
4419 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
4420 // window.
4421 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
chaviw3277faf2021-05-19 16:45:23 -05004422 mUnfocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL |
4423 WindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
4424 WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004425
4426 mFocusedWindow =
4427 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05004428 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004429 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05004430 mFocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004431
4432 // Set focused application.
4433 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07004434 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004435
4436 // Expect one focus window exist in display.
4437 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004438 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004439 mFocusedWindow->consumeFocusEvent(true);
4440 }
4441
4442 virtual void TearDown() override {
4443 InputDispatcherTest::TearDown();
4444
4445 mUnfocusedWindow.clear();
4446 mFocusedWindow.clear();
4447 }
4448
4449protected:
Chris Yea209fde2020-07-22 13:54:51 -07004450 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004451 sp<FakeWindowHandle> mUnfocusedWindow;
4452 sp<FakeWindowHandle> mFocusedWindow;
4453 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
4454 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
4455 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
4456
4457 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
4458
4459 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
4460
4461private:
4462 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004463 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004464 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4465 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004467 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4468 location));
4469 }
4470};
4471
4472// If we have 2 windows that are both unresponsive, the one with the shortest timeout
4473// should be ANR'd first.
4474TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004475 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004476 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4477 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004478 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004479 mFocusedWindow->consumeMotionDown();
4480 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4481 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4482 // We consumed all events, so no ANR
4483 ASSERT_TRUE(mDispatcher->waitForIdle());
4484 mFakePolicy->assertNotifyAnrWasNotCalled();
4485
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004487 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4488 FOCUSED_WINDOW_LOCATION));
4489 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
4490 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004491
4492 const std::chrono::duration timeout =
4493 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004494 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004495 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
4496 // sequence to make it consistent
4497 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004498 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004499 mFocusedWindow->consumeMotionDown();
4500 // This cancel is generated because the connection was unresponsive
4501 mFocusedWindow->consumeMotionCancel();
4502 mFocusedWindow->assertNoEvents();
4503 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004504 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004505 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004506 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004507}
4508
4509// If we have 2 windows with identical timeouts that are both unresponsive,
4510// it doesn't matter which order they should have ANR.
4511// But we should receive ANR for both.
4512TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
4513 // Set the timeout for unfocused window to match the focused window
4514 mUnfocusedWindow->setDispatchingTimeout(10ms);
4515 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
4516
4517 tapOnFocusedWindow();
4518 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004519 sp<IBinder> anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms);
4520 sp<IBinder> anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004521
4522 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004523 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
4524 mFocusedWindow->getToken() == anrConnectionToken2);
4525 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
4526 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004527
4528 ASSERT_TRUE(mDispatcher->waitForIdle());
4529 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004530
4531 mFocusedWindow->consumeMotionDown();
4532 mFocusedWindow->consumeMotionUp();
4533 mUnfocusedWindow->consumeMotionOutside();
4534
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004535 sp<IBinder> responsiveToken1 = mFakePolicy->getResponsiveWindowToken();
4536 sp<IBinder> responsiveToken2 = mFakePolicy->getResponsiveWindowToken();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004537
4538 // Both applications should be marked as responsive, in any order
4539 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
4540 mFocusedWindow->getToken() == responsiveToken2);
4541 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
4542 mUnfocusedWindow->getToken() == responsiveToken2);
4543 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004544}
4545
4546// If a window is already not responding, the second tap on the same window should be ignored.
4547// We should also log an error to account for the dropped event (not tested here).
4548// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
4549TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
4550 tapOnFocusedWindow();
4551 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4552 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4553 // Receive the events, but don't respond
4554 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
4555 ASSERT_TRUE(downEventSequenceNum);
4556 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
4557 ASSERT_TRUE(upEventSequenceNum);
4558 const std::chrono::duration timeout =
4559 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004560 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004561
4562 // Tap once again
4563 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004564 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004565 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4566 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004567 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004568 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4569 FOCUSED_WINDOW_LOCATION));
4570 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
4571 // valid touch target
4572 mUnfocusedWindow->assertNoEvents();
4573
4574 // Consume the first tap
4575 mFocusedWindow->finishEvent(*downEventSequenceNum);
4576 mFocusedWindow->finishEvent(*upEventSequenceNum);
4577 ASSERT_TRUE(mDispatcher->waitForIdle());
4578 // The second tap did not go to the focused window
4579 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004580 // Since all events are finished, connection should be deemed healthy again
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004581 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004582 mFakePolicy->assertNotifyAnrWasNotCalled();
4583}
4584
4585// If you tap outside of all windows, there will not be ANR
4586TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004587 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004588 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4589 LOCATION_OUTSIDE_ALL_WINDOWS));
4590 ASSERT_TRUE(mDispatcher->waitForIdle());
4591 mFakePolicy->assertNotifyAnrWasNotCalled();
4592}
4593
4594// Since the focused window is paused, tapping on it should not produce any events
4595TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
4596 mFocusedWindow->setPaused(true);
4597 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
4598
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004599 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004600 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4601 FOCUSED_WINDOW_LOCATION));
4602
4603 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
4604 ASSERT_TRUE(mDispatcher->waitForIdle());
4605 // Should not ANR because the window is paused, and touches shouldn't go to it
4606 mFakePolicy->assertNotifyAnrWasNotCalled();
4607
4608 mFocusedWindow->assertNoEvents();
4609 mUnfocusedWindow->assertNoEvents();
4610}
4611
4612/**
4613 * If a window is processing a motion event, and then a key event comes in, the key event should
4614 * not to to the focused window until the motion is processed.
4615 * If a different window becomes focused at this time, the key should go to that window instead.
4616 *
4617 * Warning!!!
4618 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
4619 * and the injection timeout that we specify when injecting the key.
4620 * We must have the injection timeout (10ms) be smaller than
4621 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
4622 *
4623 * If that value changes, this test should also change.
4624 */
4625TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
4626 // Set a long ANR timeout to prevent it from triggering
4627 mFocusedWindow->setDispatchingTimeout(2s);
4628 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
4629
4630 tapOnUnfocusedWindow();
4631 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
4632 ASSERT_TRUE(downSequenceNum);
4633 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
4634 ASSERT_TRUE(upSequenceNum);
4635 // Don't finish the events yet, and send a key
4636 // Injection will succeed because we will eventually give up and send the key to the focused
4637 // window even if motions are still being processed.
4638
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004639 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004640 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004641 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
4642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004643 // Key will not be sent to the window, yet, because the window is still processing events
4644 // and the key remains pending, waiting for the touch events to be processed
4645 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
4646 ASSERT_FALSE(keySequenceNum);
4647
4648 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07004649 mFocusedWindow->setFocusable(false);
4650 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004651 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004652 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004653
4654 // Focus events should precede the key events
4655 mUnfocusedWindow->consumeFocusEvent(true);
4656 mFocusedWindow->consumeFocusEvent(false);
4657
4658 // Finish the tap events, which should unblock dispatcher
4659 mUnfocusedWindow->finishEvent(*downSequenceNum);
4660 mUnfocusedWindow->finishEvent(*upSequenceNum);
4661
4662 // Now that all queues are cleared and no backlog in the connections, the key event
4663 // can finally go to the newly focused "mUnfocusedWindow".
4664 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4665 mFocusedWindow->assertNoEvents();
4666 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004667 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004668}
4669
4670// When the touch stream is split across 2 windows, and one of them does not respond,
4671// then ANR should be raised and the touch should be canceled for the unresponsive window.
4672// The other window should not be affected by that.
4673TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
4674 // Touch Window 1
4675 NotifyMotionArgs motionArgs =
4676 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4677 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
4678 mDispatcher->notifyMotion(&motionArgs);
4679 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4680 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4681
4682 // Touch Window 2
4683 int32_t actionPointerDown =
4684 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
4685
4686 motionArgs =
4687 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4688 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
4689 mDispatcher->notifyMotion(&motionArgs);
4690
4691 const std::chrono::duration timeout =
4692 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004693 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004694
4695 mUnfocusedWindow->consumeMotionDown();
4696 mFocusedWindow->consumeMotionDown();
4697 // Focused window may or may not receive ACTION_MOVE
4698 // But it should definitely receive ACTION_CANCEL due to the ANR
4699 InputEvent* event;
4700 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
4701 ASSERT_TRUE(moveOrCancelSequenceNum);
4702 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
4703 ASSERT_NE(nullptr, event);
4704 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
4705 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
4706 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
4707 mFocusedWindow->consumeMotionCancel();
4708 } else {
4709 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
4710 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004711 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004712 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004713
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004714 mUnfocusedWindow->assertNoEvents();
4715 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004716 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004717}
4718
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05004719/**
4720 * If we have no focused window, and a key comes in, we start the ANR timer.
4721 * The focused application should add a focused window before the timer runs out to prevent ANR.
4722 *
4723 * If the user touches another application during this time, the key should be dropped.
4724 * Next, if a new focused window comes in, without toggling the focused application,
4725 * then no ANR should occur.
4726 *
4727 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
4728 * but in some cases the policy may not update the focused application.
4729 */
4730TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
4731 std::shared_ptr<FakeApplicationHandle> focusedApplication =
4732 std::make_shared<FakeApplicationHandle>();
4733 focusedApplication->setDispatchingTimeout(60ms);
4734 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
4735 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
4736 mFocusedWindow->setFocusable(false);
4737
4738 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
4739 mFocusedWindow->consumeFocusEvent(false);
4740
4741 // Send a key. The ANR timer should start because there is no focused window.
4742 // 'focusedApplication' will get blamed if this timer completes.
4743 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004744 InputEventInjectionResult result =
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05004745 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004746 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
4747 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004748 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05004749
4750 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
4751 // then the injected touches won't cause the focused event to get dropped.
4752 // The dispatcher only checks for whether the queue should be pruned upon queueing.
4753 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
4754 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
4755 // For this test, it means that the key would get delivered to the window once it becomes
4756 // focused.
4757 std::this_thread::sleep_for(10ms);
4758
4759 // Touch unfocused window. This should force the pending key to get dropped.
4760 NotifyMotionArgs motionArgs =
4761 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4762 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
4763 mDispatcher->notifyMotion(&motionArgs);
4764
4765 // We do not consume the motion right away, because that would require dispatcher to first
4766 // process (== drop) the key event, and by that time, ANR will be raised.
4767 // Set the focused window first.
4768 mFocusedWindow->setFocusable(true);
4769 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
4770 setFocusedWindow(mFocusedWindow);
4771 mFocusedWindow->consumeFocusEvent(true);
4772 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
4773 // to another application. This could be a bug / behaviour in the policy.
4774
4775 mUnfocusedWindow->consumeMotionDown();
4776
4777 ASSERT_TRUE(mDispatcher->waitForIdle());
4778 // Should not ANR because we actually have a focused window. It was just added too slowly.
4779 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
4780}
4781
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05004782// These tests ensure we cannot send touch events to a window that's positioned behind a window
4783// that has feature NO_INPUT_CHANNEL.
4784// Layout:
4785// Top (closest to user)
4786// mNoInputWindow (above all windows)
4787// mBottomWindow
4788// Bottom (furthest from user)
4789class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
4790 virtual void SetUp() override {
4791 InputDispatcherTest::SetUp();
4792
4793 mApplication = std::make_shared<FakeApplicationHandle>();
4794 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
4795 "Window without input channel", ADISPLAY_ID_DEFAULT,
4796 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
4797
chaviw3277faf2021-05-19 16:45:23 -05004798 mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05004799 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
4800 // It's perfectly valid for this window to not have an associated input channel
4801
4802 mBottomWindow = new FakeWindowHandle(mApplication, mDispatcher, "Bottom window",
4803 ADISPLAY_ID_DEFAULT);
4804 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
4805
4806 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
4807 }
4808
4809protected:
4810 std::shared_ptr<FakeApplicationHandle> mApplication;
4811 sp<FakeWindowHandle> mNoInputWindow;
4812 sp<FakeWindowHandle> mBottomWindow;
4813};
4814
4815TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
4816 PointF touchedPoint = {10, 10};
4817
4818 NotifyMotionArgs motionArgs =
4819 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4820 ADISPLAY_ID_DEFAULT, {touchedPoint});
4821 mDispatcher->notifyMotion(&motionArgs);
4822
4823 mNoInputWindow->assertNoEvents();
4824 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
4825 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
4826 // and therefore should prevent mBottomWindow from receiving touches
4827 mBottomWindow->assertNoEvents();
4828}
4829
4830/**
4831 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
4832 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
4833 */
4834TEST_F(InputDispatcherMultiWindowOcclusionTests,
4835 NoInputChannelFeature_DropsTouchesWithValidChannel) {
4836 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
4837 "Window with input channel and NO_INPUT_CHANNEL",
4838 ADISPLAY_ID_DEFAULT);
4839
chaviw3277faf2021-05-19 16:45:23 -05004840 mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05004841 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
4842 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
4843
4844 PointF touchedPoint = {10, 10};
4845
4846 NotifyMotionArgs motionArgs =
4847 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4848 ADISPLAY_ID_DEFAULT, {touchedPoint});
4849 mDispatcher->notifyMotion(&motionArgs);
4850
4851 mNoInputWindow->assertNoEvents();
4852 mBottomWindow->assertNoEvents();
4853}
4854
Vishnu Nair958da932020-08-21 17:12:37 -07004855class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
4856protected:
4857 std::shared_ptr<FakeApplicationHandle> mApp;
4858 sp<FakeWindowHandle> mWindow;
4859 sp<FakeWindowHandle> mMirror;
4860
4861 virtual void SetUp() override {
4862 InputDispatcherTest::SetUp();
4863 mApp = std::make_shared<FakeApplicationHandle>();
4864 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
4865 mMirror = new FakeWindowHandle(mApp, mDispatcher, "TestWindowMirror", ADISPLAY_ID_DEFAULT,
4866 mWindow->getToken());
4867 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
4868 mWindow->setFocusable(true);
4869 mMirror->setFocusable(true);
4870 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4871 }
4872};
4873
4874TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
4875 // Request focus on a mirrored window
4876 setFocusedWindow(mMirror);
4877
4878 // window gets focused
4879 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4881 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004882 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
4883}
4884
4885// A focused & mirrored window remains focused only if the window and its mirror are both
4886// focusable.
4887TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
4888 setFocusedWindow(mMirror);
4889
4890 // window gets focused
4891 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4893 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004894 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4896 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004897 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4898
4899 mMirror->setFocusable(false);
4900 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4901
4902 // window loses focus since one of the windows associated with the token in not focusable
4903 mWindow->consumeFocusEvent(false);
4904
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004905 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4906 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004907 mWindow->assertNoEvents();
4908}
4909
4910// A focused & mirrored window remains focused until the window and its mirror both become
4911// invisible.
4912TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
4913 setFocusedWindow(mMirror);
4914
4915 // window gets focused
4916 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004917 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4918 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004919 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4921 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004922 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4923
4924 mMirror->setVisible(false);
4925 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4926
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 mWindow->setVisible(false);
4935 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4936
4937 // window loses focus only after all windows associated with the token become invisible.
4938 mWindow->consumeFocusEvent(false);
4939
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004940 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4941 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004942 mWindow->assertNoEvents();
4943}
4944
4945// A focused & mirrored window remains focused until both windows are removed.
4946TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
4947 setFocusedWindow(mMirror);
4948
4949 // window gets focused
4950 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004951 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4952 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004953 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4955 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004956 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4957
4958 // single window is removed but the window token remains focused
4959 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
4960
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 // Both windows are removed
4969 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
4970 mWindow->consumeFocusEvent(false);
4971
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004972 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4973 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004974 mWindow->assertNoEvents();
4975}
4976
4977// Focus request can be pending until one window becomes visible.
4978TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
4979 // Request focus on an invisible mirror.
4980 mWindow->setVisible(false);
4981 mMirror->setVisible(false);
4982 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4983 setFocusedWindow(mMirror);
4984
4985 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07004987 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004988 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07004989
4990 mMirror->setVisible(true);
4991 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4992
4993 // window gets focused
4994 mWindow->consumeFocusEvent(true);
4995 // window gets the pending key event
4996 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4997}
Prabir Pradhan99987712020-11-10 18:43:05 -08004998
4999class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
5000protected:
5001 std::shared_ptr<FakeApplicationHandle> mApp;
5002 sp<FakeWindowHandle> mWindow;
5003 sp<FakeWindowHandle> mSecondWindow;
5004
5005 void SetUp() override {
5006 InputDispatcherTest::SetUp();
5007 mApp = std::make_shared<FakeApplicationHandle>();
5008 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
5009 mWindow->setFocusable(true);
5010 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
5011 mSecondWindow->setFocusable(true);
5012
5013 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5014 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
5015
5016 setFocusedWindow(mWindow);
5017 mWindow->consumeFocusEvent(true);
5018 }
5019
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005020 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
5021 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005022 mDispatcher->notifyPointerCaptureChanged(&args);
5023 }
5024
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005025 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
5026 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08005027 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005028 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
5029 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005030 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005031 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08005032 }
5033};
5034
5035TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
5036 // Ensure that capture cannot be obtained for unfocused windows.
5037 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
5038 mFakePolicy->assertSetPointerCaptureNotCalled();
5039 mSecondWindow->assertNoEvents();
5040
5041 // Ensure that capture can be enabled from the focus window.
5042 requestAndVerifyPointerCapture(mWindow, true);
5043
5044 // Ensure that capture cannot be disabled from a window that does not have capture.
5045 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
5046 mFakePolicy->assertSetPointerCaptureNotCalled();
5047
5048 // Ensure that capture can be disabled from the window with capture.
5049 requestAndVerifyPointerCapture(mWindow, false);
5050}
5051
5052TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005053 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08005054
5055 setFocusedWindow(mSecondWindow);
5056
5057 // Ensure that the capture disabled event was sent first.
5058 mWindow->consumeCaptureEvent(false);
5059 mWindow->consumeFocusEvent(false);
5060 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005061 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08005062
5063 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005064 notifyPointerCaptureChanged({});
5065 notifyPointerCaptureChanged(request);
5066 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08005067 mWindow->assertNoEvents();
5068 mSecondWindow->assertNoEvents();
5069 mFakePolicy->assertSetPointerCaptureNotCalled();
5070}
5071
5072TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005073 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08005074
5075 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005076 notifyPointerCaptureChanged({});
5077 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005078
5079 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005080 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08005081 mWindow->consumeCaptureEvent(false);
5082 mWindow->assertNoEvents();
5083}
5084
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005085TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
5086 requestAndVerifyPointerCapture(mWindow, true);
5087
5088 // The first window loses focus.
5089 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005090 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005091 mWindow->consumeCaptureEvent(false);
5092
5093 // Request Pointer Capture from the second window before the notification from InputReader
5094 // arrives.
5095 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005096 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005097
5098 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005099 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005100
5101 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005102 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005103
5104 mSecondWindow->consumeFocusEvent(true);
5105 mSecondWindow->consumeCaptureEvent(true);
5106}
5107
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005108TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
5109 // App repeatedly enables and disables capture.
5110 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
5111 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
5112 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
5113 mFakePolicy->assertSetPointerCaptureCalled(false);
5114 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
5115 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
5116
5117 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
5118 // first request is now stale, this should do nothing.
5119 notifyPointerCaptureChanged(firstRequest);
5120 mWindow->assertNoEvents();
5121
5122 // InputReader notifies that the second request was enabled.
5123 notifyPointerCaptureChanged(secondRequest);
5124 mWindow->consumeCaptureEvent(true);
5125}
5126
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005127class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
5128protected:
5129 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00005130
5131 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
5132 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
5133
5134 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
5135 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
5136
5137 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
5138 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
5139 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
5140 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
5141 MAXIMUM_OBSCURING_OPACITY);
5142
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005143 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005144 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005145 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005146
5147 sp<FakeWindowHandle> mTouchWindow;
5148
5149 virtual void SetUp() override {
5150 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005151 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005152 mDispatcher->setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode::BLOCK);
5153 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
5154 }
5155
5156 virtual void TearDown() override {
5157 InputDispatcherTest::TearDown();
5158 mTouchWindow.clear();
5159 }
5160
chaviw3277faf2021-05-19 16:45:23 -05005161 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
5162 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005163 sp<FakeWindowHandle> window = getWindow(uid, name);
chaviw3277faf2021-05-19 16:45:23 -05005164 window->setFlags(WindowInfo::Flag::NOT_TOUCHABLE);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005165 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005166 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005167 return window;
5168 }
5169
5170 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
5171 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
5172 sp<FakeWindowHandle> window =
5173 new FakeWindowHandle(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
5174 // Generate an arbitrary PID based on the UID
5175 window->setOwnerInfo(1777 + (uid % 10000), uid);
5176 return window;
5177 }
5178
5179 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
5180 NotifyMotionArgs args =
5181 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5182 ADISPLAY_ID_DEFAULT, points);
5183 mDispatcher->notifyMotion(&args);
5184 }
5185};
5186
5187TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005188 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005189 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005190 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005191
5192 touch();
5193
5194 mTouchWindow->assertNoEvents();
5195}
5196
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005197TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00005198 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
5199 const sp<FakeWindowHandle>& w =
5200 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
5201 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5202
5203 touch();
5204
5205 mTouchWindow->assertNoEvents();
5206}
5207
5208TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005209 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
5210 const sp<FakeWindowHandle>& w =
5211 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
5212 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5213
5214 touch();
5215
5216 w->assertNoEvents();
5217}
5218
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005219TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005220 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
5221 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005222
5223 touch();
5224
5225 mTouchWindow->consumeAnyMotionDown();
5226}
5227
5228TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005229 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005230 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005231 w->setFrame(Rect(0, 0, 50, 50));
5232 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005233
5234 touch({PointF{100, 100}});
5235
5236 mTouchWindow->consumeAnyMotionDown();
5237}
5238
5239TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005240 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005241 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005242 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5243
5244 touch();
5245
5246 mTouchWindow->consumeAnyMotionDown();
5247}
5248
5249TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
5250 const sp<FakeWindowHandle>& w =
5251 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
5252 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005253
5254 touch();
5255
5256 mTouchWindow->consumeAnyMotionDown();
5257}
5258
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005259TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
5260 const sp<FakeWindowHandle>& w =
5261 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
5262 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5263
5264 touch();
5265
5266 w->assertNoEvents();
5267}
5268
5269/**
5270 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
5271 * inside) while letting them pass-through. Note that even though touch passes through the occluding
5272 * window, the occluding window will still receive ACTION_OUTSIDE event.
5273 */
5274TEST_F(InputDispatcherUntrustedTouchesTest,
5275 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
5276 const sp<FakeWindowHandle>& w =
5277 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
chaviw3277faf2021-05-19 16:45:23 -05005278 w->addFlags(WindowInfo::Flag::WATCH_OUTSIDE_TOUCH);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005279 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5280
5281 touch();
5282
5283 w->consumeMotionOutside();
5284}
5285
5286TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
5287 const sp<FakeWindowHandle>& w =
5288 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
chaviw3277faf2021-05-19 16:45:23 -05005289 w->addFlags(WindowInfo::Flag::WATCH_OUTSIDE_TOUCH);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005290 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5291
5292 touch();
5293
5294 InputEvent* event = w->consume();
5295 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
5296 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
5297 EXPECT_EQ(0.0f, motionEvent.getRawPointerCoords(0)->getX());
5298 EXPECT_EQ(0.0f, motionEvent.getRawPointerCoords(0)->getY());
5299}
5300
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005301TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005302 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005303 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5304 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005305 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5306
5307 touch();
5308
5309 mTouchWindow->consumeAnyMotionDown();
5310}
5311
5312TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
5313 const sp<FakeWindowHandle>& w =
5314 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5315 MAXIMUM_OBSCURING_OPACITY);
5316 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005317
5318 touch();
5319
5320 mTouchWindow->consumeAnyMotionDown();
5321}
5322
5323TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005324 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005325 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5326 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005327 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5328
5329 touch();
5330
5331 mTouchWindow->assertNoEvents();
5332}
5333
5334TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
5335 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
5336 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005337 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
5338 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005339 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005340 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
5341 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005342 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5343
5344 touch();
5345
5346 mTouchWindow->assertNoEvents();
5347}
5348
5349TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
5350 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
5351 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005352 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
5353 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005354 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005355 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
5356 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005357 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5358
5359 touch();
5360
5361 mTouchWindow->consumeAnyMotionDown();
5362}
5363
5364TEST_F(InputDispatcherUntrustedTouchesTest,
5365 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
5366 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005367 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5368 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005369 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005370 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5371 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005372 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
5373
5374 touch();
5375
5376 mTouchWindow->consumeAnyMotionDown();
5377}
5378
5379TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
5380 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005381 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5382 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005383 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005384 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5385 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005386 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005387
5388 touch();
5389
5390 mTouchWindow->assertNoEvents();
5391}
5392
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005393TEST_F(InputDispatcherUntrustedTouchesTest,
5394 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
5395 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005396 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5397 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005398 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005399 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5400 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005401 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
5402
5403 touch();
5404
5405 mTouchWindow->assertNoEvents();
5406}
5407
5408TEST_F(InputDispatcherUntrustedTouchesTest,
5409 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
5410 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005411 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5412 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005413 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005414 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5415 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005416 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
5417
5418 touch();
5419
5420 mTouchWindow->consumeAnyMotionDown();
5421}
5422
5423TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
5424 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005425 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5426 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005427 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5428
5429 touch();
5430
5431 mTouchWindow->consumeAnyMotionDown();
5432}
5433
5434TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
5435 const sp<FakeWindowHandle>& w =
5436 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
5437 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5438
5439 touch();
5440
5441 mTouchWindow->consumeAnyMotionDown();
5442}
5443
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00005444TEST_F(InputDispatcherUntrustedTouchesTest,
5445 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
5446 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
5447 const sp<FakeWindowHandle>& w =
5448 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
5449 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5450
5451 touch();
5452
5453 mTouchWindow->assertNoEvents();
5454}
5455
5456TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
5457 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
5458 const sp<FakeWindowHandle>& w =
5459 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
5460 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5461
5462 touch();
5463
5464 mTouchWindow->consumeAnyMotionDown();
5465}
5466
5467TEST_F(InputDispatcherUntrustedTouchesTest,
5468 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
5469 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
5470 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005471 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5472 OPACITY_ABOVE_THRESHOLD);
5473 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5474
5475 touch();
5476
5477 mTouchWindow->consumeAnyMotionDown();
5478}
5479
5480TEST_F(InputDispatcherUntrustedTouchesTest,
5481 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
5482 const sp<FakeWindowHandle>& w1 =
5483 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
5484 OPACITY_BELOW_THRESHOLD);
5485 const sp<FakeWindowHandle>& w2 =
5486 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5487 OPACITY_BELOW_THRESHOLD);
5488 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5489
5490 touch();
5491
5492 mTouchWindow->assertNoEvents();
5493}
5494
5495/**
5496 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
5497 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
5498 * (which alone would result in allowing touches) does not affect the blocking behavior.
5499 */
5500TEST_F(InputDispatcherUntrustedTouchesTest,
5501 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
5502 const sp<FakeWindowHandle>& wB =
5503 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
5504 OPACITY_BELOW_THRESHOLD);
5505 const sp<FakeWindowHandle>& wC =
5506 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5507 OPACITY_BELOW_THRESHOLD);
5508 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
5509
5510 touch();
5511
5512 mTouchWindow->assertNoEvents();
5513}
5514
5515/**
5516 * This test is testing that a window from a different UID but with same application token doesn't
5517 * block the touch. Apps can share the application token for close UI collaboration for example.
5518 */
5519TEST_F(InputDispatcherUntrustedTouchesTest,
5520 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
5521 const sp<FakeWindowHandle>& w =
5522 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
5523 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00005524 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5525
5526 touch();
5527
5528 mTouchWindow->consumeAnyMotionDown();
5529}
5530
arthurhungb89ccb02020-12-30 16:19:01 +08005531class InputDispatcherDragTests : public InputDispatcherTest {
5532protected:
5533 std::shared_ptr<FakeApplicationHandle> mApp;
5534 sp<FakeWindowHandle> mWindow;
5535 sp<FakeWindowHandle> mSecondWindow;
5536 sp<FakeWindowHandle> mDragWindow;
5537
5538 void SetUp() override {
5539 InputDispatcherTest::SetUp();
5540 mApp = std::make_shared<FakeApplicationHandle>();
5541 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
5542 mWindow->setFrame(Rect(0, 0, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05005543 mWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
arthurhungb89ccb02020-12-30 16:19:01 +08005544
5545 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
5546 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
chaviw3277faf2021-05-19 16:45:23 -05005547 mSecondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
arthurhungb89ccb02020-12-30 16:19:01 +08005548
5549 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5550 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
5551 }
5552
5553 // Start performing drag, we will create a drag window and transfer touch to it.
5554 void performDrag() {
5555 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5556 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5557 {50, 50}))
5558 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5559
5560 // Window should receive motion event.
5561 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5562
5563 // The drag window covers the entire display
5564 mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
5565 mDispatcher->setInputWindows(
5566 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5567
5568 // Transfer touch focus to the drag window
5569 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
5570 true /* isDragDrop */);
5571 mWindow->consumeMotionCancel();
5572 mDragWindow->consumeMotionDown();
5573 }
arthurhung6d4bed92021-03-17 11:59:33 +08005574
5575 // Start performing drag, we will create a drag window and transfer touch to it.
5576 void performStylusDrag() {
5577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5578 injectMotionEvent(mDispatcher,
5579 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
5580 AINPUT_SOURCE_STYLUS)
5581 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
5582 .pointer(PointerBuilder(0,
5583 AMOTION_EVENT_TOOL_TYPE_STYLUS)
5584 .x(50)
5585 .y(50))
5586 .build()));
5587 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5588
5589 // The drag window covers the entire display
5590 mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
5591 mDispatcher->setInputWindows(
5592 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5593
5594 // Transfer touch focus to the drag window
5595 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
5596 true /* isDragDrop */);
5597 mWindow->consumeMotionCancel();
5598 mDragWindow->consumeMotionDown();
5599 }
arthurhungb89ccb02020-12-30 16:19:01 +08005600};
5601
5602TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
5603 performDrag();
5604
5605 // Move on window.
5606 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5607 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5608 ADISPLAY_ID_DEFAULT, {50, 50}))
5609 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5610 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5611 mWindow->consumeDragEvent(false, 50, 50);
5612 mSecondWindow->assertNoEvents();
5613
5614 // Move to another window.
5615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5616 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5617 ADISPLAY_ID_DEFAULT, {150, 50}))
5618 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5619 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5620 mWindow->consumeDragEvent(true, 150, 50);
5621 mSecondWindow->consumeDragEvent(false, 50, 50);
5622
5623 // Move back to original window.
5624 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5625 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5626 ADISPLAY_ID_DEFAULT, {50, 50}))
5627 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5628 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5629 mWindow->consumeDragEvent(false, 50, 50);
5630 mSecondWindow->consumeDragEvent(true, -50, 50);
5631
5632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5633 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
5634 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5635 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5636 mWindow->assertNoEvents();
5637 mSecondWindow->assertNoEvents();
5638}
5639
arthurhungf452d0b2021-01-06 00:19:52 +08005640TEST_F(InputDispatcherDragTests, DragAndDrop) {
5641 performDrag();
5642
5643 // Move on window.
5644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5645 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5646 ADISPLAY_ID_DEFAULT, {50, 50}))
5647 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5648 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5649 mWindow->consumeDragEvent(false, 50, 50);
5650 mSecondWindow->assertNoEvents();
5651
5652 // Move to another window.
5653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5654 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5655 ADISPLAY_ID_DEFAULT, {150, 50}))
5656 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5657 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5658 mWindow->consumeDragEvent(true, 150, 50);
5659 mSecondWindow->consumeDragEvent(false, 50, 50);
5660
5661 // drop to another window.
5662 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5663 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5664 {150, 50}))
5665 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5666 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5667 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
5668 mWindow->assertNoEvents();
5669 mSecondWindow->assertNoEvents();
5670}
5671
arthurhung6d4bed92021-03-17 11:59:33 +08005672TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
5673 performStylusDrag();
5674
5675 // Move on window and keep button pressed.
5676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5677 injectMotionEvent(mDispatcher,
5678 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
5679 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
5680 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5681 .x(50)
5682 .y(50))
5683 .build()))
5684 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5685 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5686 mWindow->consumeDragEvent(false, 50, 50);
5687 mSecondWindow->assertNoEvents();
5688
5689 // Move to another window and release button, expect to drop item.
5690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5691 injectMotionEvent(mDispatcher,
5692 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
5693 .buttonState(0)
5694 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5695 .x(150)
5696 .y(50))
5697 .build()))
5698 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5699 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5700 mWindow->assertNoEvents();
5701 mSecondWindow->assertNoEvents();
5702 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
5703
5704 // nothing to the window.
5705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5706 injectMotionEvent(mDispatcher,
5707 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
5708 .buttonState(0)
5709 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5710 .x(150)
5711 .y(50))
5712 .build()))
5713 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5714 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5715 mWindow->assertNoEvents();
5716 mSecondWindow->assertNoEvents();
5717}
5718
Arthur Hung6d0571e2021-04-09 20:18:16 +08005719TEST_F(InputDispatcherDragTests, DragAndDrop_InvalidWindow) {
5720 performDrag();
5721
5722 // Set second window invisible.
5723 mSecondWindow->setVisible(false);
5724 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5725
5726 // Move on window.
5727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5728 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5729 ADISPLAY_ID_DEFAULT, {50, 50}))
5730 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5731 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5732 mWindow->consumeDragEvent(false, 50, 50);
5733 mSecondWindow->assertNoEvents();
5734
5735 // Move to another window.
5736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5737 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5738 ADISPLAY_ID_DEFAULT, {150, 50}))
5739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5740 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5741 mWindow->consumeDragEvent(true, 150, 50);
5742 mSecondWindow->assertNoEvents();
5743
5744 // drop to another window.
5745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5746 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5747 {150, 50}))
5748 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5749 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5750 mFakePolicy->assertDropTargetEquals(nullptr);
5751 mWindow->assertNoEvents();
5752 mSecondWindow->assertNoEvents();
5753}
5754
Vishnu Nair062a8672021-09-03 16:07:44 -07005755class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
5756
5757TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
5758 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5759 sp<FakeWindowHandle> window =
5760 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
5761 window->setInputFeatures(WindowInfo::Feature::DROP_INPUT);
5762 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5763 window->setFocusable(true);
5764 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5765 setFocusedWindow(window);
5766 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
5767
5768 // With the flag set, window should not get any input
5769 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
5770 mDispatcher->notifyKey(&keyArgs);
5771 window->assertNoEvents();
5772
5773 NotifyMotionArgs motionArgs =
5774 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5775 ADISPLAY_ID_DEFAULT);
5776 mDispatcher->notifyMotion(&motionArgs);
5777 window->assertNoEvents();
5778
5779 // With the flag cleared, the window should get input
5780 window->setInputFeatures({});
5781 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5782
5783 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
5784 mDispatcher->notifyKey(&keyArgs);
5785 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
5786
5787 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5788 ADISPLAY_ID_DEFAULT);
5789 mDispatcher->notifyMotion(&motionArgs);
5790 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5791 window->assertNoEvents();
5792}
5793
5794TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
5795 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
5796 std::make_shared<FakeApplicationHandle>();
5797 sp<FakeWindowHandle> obscuringWindow =
5798 new FakeWindowHandle(obscuringApplication, mDispatcher, "obscuringWindow",
5799 ADISPLAY_ID_DEFAULT);
5800 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
5801 obscuringWindow->setOwnerInfo(111, 111);
5802 obscuringWindow->setFlags(WindowInfo::Flag::NOT_TOUCHABLE);
5803 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5804 sp<FakeWindowHandle> window =
5805 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
5806 window->setInputFeatures(WindowInfo::Feature::DROP_INPUT_IF_OBSCURED);
5807 window->setOwnerInfo(222, 222);
5808 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5809 window->setFocusable(true);
5810 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
5811 setFocusedWindow(window);
5812 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
5813
5814 // With the flag set, window should not get any input
5815 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
5816 mDispatcher->notifyKey(&keyArgs);
5817 window->assertNoEvents();
5818
5819 NotifyMotionArgs motionArgs =
5820 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5821 ADISPLAY_ID_DEFAULT);
5822 mDispatcher->notifyMotion(&motionArgs);
5823 window->assertNoEvents();
5824
5825 // With the flag cleared, the window should get input
5826 window->setInputFeatures({});
5827 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
5828
5829 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
5830 mDispatcher->notifyKey(&keyArgs);
5831 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
5832
5833 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5834 ADISPLAY_ID_DEFAULT);
5835 mDispatcher->notifyMotion(&motionArgs);
5836 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5837 window->assertNoEvents();
5838}
5839
5840TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
5841 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
5842 std::make_shared<FakeApplicationHandle>();
5843 sp<FakeWindowHandle> obscuringWindow =
5844 new FakeWindowHandle(obscuringApplication, mDispatcher, "obscuringWindow",
5845 ADISPLAY_ID_DEFAULT);
5846 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
5847 obscuringWindow->setOwnerInfo(111, 111);
5848 obscuringWindow->setFlags(WindowInfo::Flag::NOT_TOUCHABLE);
5849 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5850 sp<FakeWindowHandle> window =
5851 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
5852 window->setInputFeatures(WindowInfo::Feature::DROP_INPUT_IF_OBSCURED);
5853 window->setOwnerInfo(222, 222);
5854 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5855 window->setFocusable(true);
5856 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
5857 setFocusedWindow(window);
5858 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
5859
5860 // With the flag set, window should not get any input
5861 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
5862 mDispatcher->notifyKey(&keyArgs);
5863 window->assertNoEvents();
5864
5865 NotifyMotionArgs motionArgs =
5866 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5867 ADISPLAY_ID_DEFAULT);
5868 mDispatcher->notifyMotion(&motionArgs);
5869 window->assertNoEvents();
5870
5871 // When the window is no longer obscured because it went on top, it should get input
5872 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
5873
5874 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
5875 mDispatcher->notifyKey(&keyArgs);
5876 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
5877
5878 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5879 ADISPLAY_ID_DEFAULT);
5880 mDispatcher->notifyMotion(&motionArgs);
5881 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5882 window->assertNoEvents();
5883}
5884
Garfield Tane84e6f92019-08-29 17:28:41 -07005885} // namespace android::inputdispatcher