blob: 9881cd4c7cc9be644fef434f7bc4b7b9e70bccfe [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>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080020#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080021#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070022#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070023#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000024#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080025#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080026#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100027#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080028#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080029#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100030
Garfield Tan1c7bc862020-01-28 13:24:04 -080031#include <cinttypes>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070032#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080033#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080034#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080035
Garfield Tan1c7bc862020-01-28 13:24:04 -080036using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050037using android::gui::FocusRequest;
38using android::gui::TouchOcclusionMode;
39using android::gui::WindowInfo;
40using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080041using android::os::InputEventInjectionResult;
42using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080043
Garfield Tane84e6f92019-08-29 17:28:41 -070044namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080045
Dominik Laskowski2f01d772022-03-23 16:01:29 -070046using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080047using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070048
Michael Wrightd02c5b62014-02-10 15:10:22 -080049// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000050static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080051
52// An arbitrary device id.
Prabir Pradhan5735a322022-04-11 17:23:34 +000053static constexpr int32_t DEVICE_ID = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -080054
Jeff Brownf086ddb2014-02-11 14:28:48 -080055// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000056static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
57static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080058
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080059static constexpr int32_t POINTER_1_DOWN =
60 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000061static constexpr int32_t POINTER_2_DOWN =
62 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000063static constexpr int32_t POINTER_3_DOWN =
64 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080065static constexpr int32_t POINTER_1_UP =
66 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
67
Antonio Kantek15beb512022-06-13 22:35:41 +000068// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhan5735a322022-04-11 17:23:34 +000069static constexpr int32_t WINDOW_PID = 999;
70static constexpr int32_t WINDOW_UID = 1001;
71
Antonio Kantek15beb512022-06-13 22:35:41 +000072// The default pid and uid for the windows created on the secondary display by the test.
73static constexpr int32_t SECONDARY_WINDOW_PID = 1010;
74static constexpr int32_t SECONDARY_WINDOW_UID = 1012;
75
Prabir Pradhan5735a322022-04-11 17:23:34 +000076// The default policy flags to use for event injection by tests.
77static constexpr uint32_t DEFAULT_POLICY_FLAGS = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
Michael Wrightd02c5b62014-02-10 15:10:22 -080078
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +000079// An arbitrary pid of the gesture monitor window
80static constexpr int32_t MONITOR_PID = 2001;
81
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080082static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
83
chaviwd1c23182019-12-20 18:44:56 -080084struct PointF {
85 float x;
86 float y;
87};
Michael Wrightd02c5b62014-02-10 15:10:22 -080088
Gang Wang342c9272020-01-13 13:15:04 -050089/**
90 * Return a DOWN key event with KEYCODE_A.
91 */
92static KeyEvent getTestKeyEvent() {
93 KeyEvent event;
94
Garfield Tanfbe732e2020-01-24 11:26:14 -080095 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
96 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
97 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050098 return event;
99}
100
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000101static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
102 ASSERT_EQ(expectedAction, receivedAction)
103 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
104 << MotionEvent::actionToString(receivedAction);
105}
106
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800107MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") {
108 bool matches = action == arg.getAction();
109 if (!matches) {
110 *result_listener << "expected action " << MotionEvent::actionToString(action)
111 << ", but got " << MotionEvent::actionToString(arg.getAction());
112 }
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800113 if (action == AMOTION_EVENT_ACTION_DOWN) {
114 if (!matches) {
115 *result_listener << "; ";
116 }
117 *result_listener << "downTime should match eventTime for ACTION_DOWN events";
118 matches &= arg.getDownTime() == arg.getEventTime();
119 }
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800120 if (action == AMOTION_EVENT_ACTION_CANCEL) {
121 if (!matches) {
122 *result_listener << "; ";
123 }
124 *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set";
125 matches &= (arg.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
126 }
127 return matches;
128}
129
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800130MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
131 return arg.getDownTime() == downTime;
132}
133
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800134MATCHER_P(WithSource, source, "InputEvent with specified source") {
135 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
136 << inputEventSourceToString(arg.getSource());
137 return arg.getSource() == source;
138}
139
Michael Wrightd02c5b62014-02-10 15:10:22 -0800140// --- FakeInputDispatcherPolicy ---
141
142class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
143 InputDispatcherConfiguration mConfig;
144
Prabir Pradhanedd96402022-02-15 01:46:16 -0800145 using AnrResult = std::pair<sp<IBinder>, int32_t /*pid*/>;
146
Michael Wrightd02c5b62014-02-10 15:10:22 -0800147protected:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000148 virtual ~FakeInputDispatcherPolicy() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800149
150public:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000151 FakeInputDispatcherPolicy() {}
Jackal Guof9696682018-10-05 12:23:23 +0800152
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800153 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700154 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
155 ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_KEY);
156 EXPECT_EQ(event.getDisplayId(), args.displayId);
157
158 const auto& keyEvent = static_cast<const KeyEvent&>(event);
159 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
160 EXPECT_EQ(keyEvent.getAction(), args.action);
161 });
Jackal Guof9696682018-10-05 12:23:23 +0800162 }
163
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700164 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
165 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
166 ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_MOTION);
167 EXPECT_EQ(event.getDisplayId(), args.displayId);
168
169 const auto& motionEvent = static_cast<const MotionEvent&>(event);
170 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
171 EXPECT_EQ(motionEvent.getAction(), args.action);
172 EXPECT_EQ(motionEvent.getX(0), point.x);
173 EXPECT_EQ(motionEvent.getY(0), point.y);
174 EXPECT_EQ(motionEvent.getRawX(0), point.x);
175 EXPECT_EQ(motionEvent.getRawY(0), point.y);
176 });
Jackal Guof9696682018-10-05 12:23:23 +0800177 }
178
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700179 void assertFilterInputEventWasNotCalled() {
180 std::scoped_lock lock(mLock);
181 ASSERT_EQ(nullptr, mFilteredEvent);
182 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800183
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800184 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700185 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800186 ASSERT_TRUE(mConfigurationChangedTime)
187 << "Timed out waiting for configuration changed call";
188 ASSERT_EQ(*mConfigurationChangedTime, when);
189 mConfigurationChangedTime = std::nullopt;
190 }
191
192 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700193 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800194 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800195 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800196 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
197 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
198 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
199 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
200 mLastNotifySwitch = std::nullopt;
201 }
202
chaviwfd6d3512019-03-25 13:23:49 -0700203 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700204 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800205 ASSERT_EQ(touchedToken, mOnPointerDownToken);
206 mOnPointerDownToken.clear();
207 }
208
209 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700210 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800211 ASSERT_TRUE(mOnPointerDownToken == nullptr)
212 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700213 }
214
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700215 // This function must be called soon after the expected ANR timer starts,
216 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500217 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700218 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500219 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800220 std::unique_lock lock(mLock);
221 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500222 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800223 ASSERT_NO_FATAL_FAILURE(
224 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500225 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700226 }
227
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000228 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800229 const sp<WindowInfoHandle>& window) {
230 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
231 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
232 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500233 }
234
Prabir Pradhanedd96402022-02-15 01:46:16 -0800235 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
236 const sp<IBinder>& expectedToken,
237 int32_t expectedPid) {
238 std::unique_lock lock(mLock);
239 android::base::ScopedLockAssertion assumeLocked(mLock);
240 AnrResult result;
241 ASSERT_NO_FATAL_FAILURE(result =
242 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
243 const auto& [token, pid] = result;
244 ASSERT_EQ(expectedToken, token);
245 ASSERT_EQ(expectedPid, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500246 }
247
Prabir Pradhanedd96402022-02-15 01:46:16 -0800248 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000249 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500250 std::unique_lock lock(mLock);
251 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800252 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
253 const auto& [token, _] = result;
254 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000255 }
256
Prabir Pradhanedd96402022-02-15 01:46:16 -0800257 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
258 int32_t expectedPid) {
259 std::unique_lock lock(mLock);
260 android::base::ScopedLockAssertion assumeLocked(mLock);
261 AnrResult result;
262 ASSERT_NO_FATAL_FAILURE(
263 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
264 const auto& [token, pid] = result;
265 ASSERT_EQ(expectedToken, token);
266 ASSERT_EQ(expectedPid, pid);
267 }
268
269 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000270 sp<IBinder> getResponsiveWindowToken() {
271 std::unique_lock lock(mLock);
272 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800273 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
274 const auto& [token, _] = result;
275 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700276 }
277
278 void assertNotifyAnrWasNotCalled() {
279 std::scoped_lock lock(mLock);
280 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800281 ASSERT_TRUE(mAnrWindows.empty());
282 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500283 << "ANR was not called, but please also consume the 'connection is responsive' "
284 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700285 }
286
Garfield Tan1c7bc862020-01-28 13:24:04 -0800287 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
288 mConfig.keyRepeatTimeout = timeout;
289 mConfig.keyRepeatDelay = delay;
290 }
291
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000292 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800293 std::unique_lock lock(mLock);
294 base::ScopedLockAssertion assumeLocked(mLock);
295
296 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
297 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000298 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800299 enabled;
300 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000301 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
302 << ") to be called.";
303 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800304 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000305 auto request = *mPointerCaptureRequest;
306 mPointerCaptureRequest.reset();
307 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800308 }
309
310 void assertSetPointerCaptureNotCalled() {
311 std::unique_lock lock(mLock);
312 base::ScopedLockAssertion assumeLocked(mLock);
313
314 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000315 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800316 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000317 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800318 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000319 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800320 }
321
arthurhungf452d0b2021-01-06 00:19:52 +0800322 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
323 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800324 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800325 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800326 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800327 }
328
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800329 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
330 std::unique_lock lock(mLock);
331 base::ScopedLockAssertion assumeLocked(mLock);
332 std::optional<sp<IBinder>> receivedToken =
333 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
334 mNotifyInputChannelBroken);
335 ASSERT_TRUE(receivedToken.has_value());
336 ASSERT_EQ(token, *receivedToken);
337 }
338
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800339 /**
340 * Set policy timeout. A value of zero means next key will not be intercepted.
341 */
342 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
343 mInterceptKeyTimeout = timeout;
344 }
345
Michael Wrightd02c5b62014-02-10 15:10:22 -0800346private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700347 std::mutex mLock;
348 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
349 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
350 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
351 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800352
Prabir Pradhan99987712020-11-10 18:43:05 -0800353 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000354
355 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800356
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700357 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700358 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800359 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
360 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700361 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800362 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
363 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700364
arthurhungf452d0b2021-01-06 00:19:52 +0800365 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800366 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800367
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800368 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
369
Prabir Pradhanedd96402022-02-15 01:46:16 -0800370 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
371 // for a specific container to become non-empty. When the container is non-empty, return the
372 // first entry from the container and erase it.
373 template <class T>
374 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
375 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
376 // If there is an ANR, Dispatcher won't be idle because there are still events
377 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
378 // before checking if ANR was called.
379 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
380 // to provide it some time to act. 100ms seems reasonable.
381 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
382 const std::chrono::time_point start = std::chrono::steady_clock::now();
383 std::optional<T> token =
384 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
385 if (!token.has_value()) {
386 ADD_FAILURE() << "Did not receive the ANR callback";
387 return {};
388 }
389
390 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
391 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
392 // the dispatcher started counting before this function was called
393 if (std::chrono::abs(timeout - waited) > 100ms) {
394 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
395 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
396 << "ms, but waited "
397 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
398 << "ms instead";
399 }
400 return *token;
401 }
402
403 template <class T>
404 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
405 std::queue<T>& storage,
406 std::unique_lock<std::mutex>& lock,
407 std::condition_variable& condition)
408 REQUIRES(mLock) {
409 condition.wait_for(lock, timeout,
410 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
411 if (storage.empty()) {
412 ADD_FAILURE() << "Did not receive the expected callback";
413 return std::nullopt;
414 }
415 T item = storage.front();
416 storage.pop();
417 return std::make_optional(item);
418 }
419
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600420 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700421 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800422 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800423 }
424
Prabir Pradhanedd96402022-02-15 01:46:16 -0800425 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
426 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700427 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800428 ASSERT_TRUE(pid.has_value());
429 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700430 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500431 }
432
Prabir Pradhanedd96402022-02-15 01:46:16 -0800433 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
434 std::optional<int32_t> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500435 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800436 ASSERT_TRUE(pid.has_value());
437 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500438 mNotifyAnr.notify_all();
439 }
440
441 void notifyNoFocusedWindowAnr(
442 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
443 std::scoped_lock lock(mLock);
444 mAnrApplications.push(applicationHandle);
445 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800446 }
447
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800448 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
449 std::scoped_lock lock(mLock);
450 mBrokenInputChannels.push(connectionToken);
451 mNotifyInputChannelBroken.notify_all();
452 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800453
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600454 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700455
Chris Yef59a2f42020-10-16 12:55:26 -0700456 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
457 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
458 const std::vector<float>& values) override {}
459
460 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
461 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000462
Chris Yefb552902021-02-03 17:18:37 -0800463 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
464
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600465 void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800466 *outConfig = mConfig;
467 }
468
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600469 bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700470 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800471 switch (inputEvent->getType()) {
472 case AINPUT_EVENT_TYPE_KEY: {
473 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800474 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800475 break;
476 }
477
478 case AINPUT_EVENT_TYPE_MOTION: {
479 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800480 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800481 break;
482 }
483 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800484 return true;
485 }
486
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800487 void interceptKeyBeforeQueueing(const KeyEvent* inputEvent, uint32_t&) override {
488 if (inputEvent->getAction() == AKEY_EVENT_ACTION_UP) {
489 // Clear intercept state when we handled the event.
490 mInterceptKeyTimeout = 0ms;
491 }
492 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800493
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600494 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800495
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600496 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800497 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
498 // Clear intercept state so we could dispatch the event in next wake.
499 mInterceptKeyTimeout = 0ms;
500 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800501 }
502
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600503 bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800504 return false;
505 }
506
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600507 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
508 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700509 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800510 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
511 * essentially a passthrough for notifySwitch.
512 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800513 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800514 }
515
Sean Stoutb4e0a592021-02-23 07:34:53 -0800516 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800517
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600518 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700519 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700520 mOnPointerDownToken = newToken;
521 }
522
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000523 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800524 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000525 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800526 mPointerCaptureChangedCondition.notify_all();
527 }
528
arthurhungf452d0b2021-01-06 00:19:52 +0800529 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
530 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800531 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800532 mDropTargetWindowToken = token;
533 }
534
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700535 void assertFilterInputEventWasCalledInternal(
536 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700537 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800538 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700539 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800540 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800541 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800542};
543
Michael Wrightd02c5b62014-02-10 15:10:22 -0800544// --- InputDispatcherTest ---
545
546class InputDispatcherTest : public testing::Test {
547protected:
548 sp<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700549 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800550
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000551 void SetUp() override {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700552 mFakePolicy = sp<FakeInputDispatcherPolicy>::make();
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800553 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800554 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000555 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700556 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800557 }
558
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000559 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700560 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800561 mFakePolicy.clear();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700562 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800563 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700564
565 /**
566 * Used for debugging when writing the test
567 */
568 void dumpDispatcherState() {
569 std::string dump;
570 mDispatcher->dump(dump);
571 std::stringstream ss(dump);
572 std::string to;
573
574 while (std::getline(ss, to, '\n')) {
575 ALOGE("%s", to.c_str());
576 }
577 }
Vishnu Nair958da932020-08-21 17:12:37 -0700578
chaviw3277faf2021-05-19 16:45:23 -0500579 void setFocusedWindow(const sp<WindowInfoHandle>& window,
580 const sp<WindowInfoHandle>& focusedWindow = nullptr) {
Vishnu Nair958da932020-08-21 17:12:37 -0700581 FocusRequest request;
582 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000583 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700584 if (focusedWindow) {
585 request.focusedToken = focusedWindow->getToken();
586 }
587 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
588 request.displayId = window->getInfo()->displayId;
589 mDispatcher->setFocusedWindow(request);
590 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800591};
592
Michael Wrightd02c5b62014-02-10 15:10:22 -0800593TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
594 KeyEvent event;
595
596 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800597 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
598 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600599 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
600 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800601 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000602 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
603 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800604 << "Should reject key events with undefined action.";
605
606 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800607 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
608 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600609 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800610 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000611 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
612 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800613 << "Should reject key events with ACTION_MULTIPLE.";
614}
615
616TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
617 MotionEvent event;
618 PointerProperties pointerProperties[MAX_POINTERS + 1];
619 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800620 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800621 pointerProperties[i].clear();
622 pointerProperties[i].id = i;
623 pointerCoords[i].clear();
624 }
625
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800626 // Some constants commonly used below
627 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
628 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
629 constexpr int32_t metaState = AMETA_NONE;
630 constexpr MotionClassification classification = MotionClassification::NONE;
631
chaviw9eaa22c2020-07-01 16:21:27 -0700632 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800633 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800634 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700635 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
636 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700637 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
638 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700639 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800640 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000641 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
642 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800643 << "Should reject motion events with undefined action.";
644
645 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800646 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800647 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
648 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
649 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
650 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500651 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800652 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000653 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
654 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800655 << "Should reject motion events with pointer down index too large.";
656
Garfield Tanfbe732e2020-01-24 11:26:14 -0800657 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700658 AMOTION_EVENT_ACTION_POINTER_DOWN |
659 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700660 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
661 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700662 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500663 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800664 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000665 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
666 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800667 << "Should reject motion events with pointer down index too small.";
668
669 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800670 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800671 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
672 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
673 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
674 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500675 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800676 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000677 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
678 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800679 << "Should reject motion events with pointer up index too large.";
680
Garfield Tanfbe732e2020-01-24 11:26:14 -0800681 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700682 AMOTION_EVENT_ACTION_POINTER_UP |
683 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700684 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
685 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700686 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500687 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800688 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000689 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
690 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800691 << "Should reject motion events with pointer up index too small.";
692
693 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800694 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
695 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700696 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700697 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
698 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700699 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800700 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000701 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
702 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800703 << "Should reject motion events with 0 pointers.";
704
Garfield Tanfbe732e2020-01-24 11:26:14 -0800705 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
706 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700707 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700708 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
709 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700710 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800711 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000712 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
713 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800714 << "Should reject motion events with more than MAX_POINTERS pointers.";
715
716 // Rejects motion events with invalid pointer ids.
717 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800718 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
719 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700720 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700721 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
722 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700723 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800724 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000725 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
726 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800727 << "Should reject motion events with pointer ids less than 0.";
728
729 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800730 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
731 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700732 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700733 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
734 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700735 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800736 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000737 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
738 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800739 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
740
741 // Rejects motion events with duplicate pointer ids.
742 pointerProperties[0].id = 1;
743 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800744 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
745 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700746 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700747 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
748 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700749 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800750 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000751 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
752 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800753 << "Should reject motion events with duplicate pointer ids.";
754}
755
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800756/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
757
758TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
759 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800760 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800761 mDispatcher->notifyConfigurationChanged(&args);
762 ASSERT_TRUE(mDispatcher->waitForIdle());
763
764 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
765}
766
767TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800768 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
769 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800770 mDispatcher->notifySwitch(&args);
771
772 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
773 args.policyFlags |= POLICY_FLAG_TRUSTED;
774 mFakePolicy->assertNotifySwitchWasCalled(args);
775}
776
Arthur Hungb92218b2018-08-14 12:00:21 +0800777// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700778static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700779// Default input dispatching timeout if there is no focused application or paused window
780// from which to determine an appropriate dispatching timeout.
781static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
782 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
783 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800784
785class FakeApplicationHandle : public InputApplicationHandle {
786public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700787 FakeApplicationHandle() {
788 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700789 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500790 mInfo.dispatchingTimeoutMillis =
791 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700792 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800793 virtual ~FakeApplicationHandle() {}
794
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000795 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700796
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500797 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
798 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700799 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800800};
801
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800802class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800803public:
Garfield Tan15601662020-09-22 15:32:38 -0700804 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800805 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700806 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800807 }
808
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800809 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700810 InputEvent* event;
811 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
812 if (!consumeSeq) {
813 return nullptr;
814 }
815 finishEvent(*consumeSeq);
816 return event;
817 }
818
819 /**
820 * Receive an event without acknowledging it.
821 * Return the sequence number that could later be used to send finished signal.
822 */
823 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800824 uint32_t consumeSeq;
825 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800826
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800827 std::chrono::time_point start = std::chrono::steady_clock::now();
828 status_t status = WOULD_BLOCK;
829 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800830 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800831 &event);
832 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
833 if (elapsed > 100ms) {
834 break;
835 }
836 }
837
838 if (status == WOULD_BLOCK) {
839 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700840 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800841 }
842
843 if (status != OK) {
844 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700845 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800846 }
847 if (event == nullptr) {
848 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700849 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800850 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700851 if (outEvent != nullptr) {
852 *outEvent = event;
853 }
854 return consumeSeq;
855 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800856
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700857 /**
858 * To be used together with "receiveEvent" to complete the consumption of an event.
859 */
860 void finishEvent(uint32_t consumeSeq) {
861 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
862 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800863 }
864
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000865 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
866 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
867 ASSERT_EQ(OK, status);
868 }
869
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000870 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
871 std::optional<int32_t> expectedDisplayId,
872 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800873 InputEvent* event = consume();
874
875 ASSERT_NE(nullptr, event) << mName.c_str()
876 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800877 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700878 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800879 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800880
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000881 if (expectedDisplayId.has_value()) {
882 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
883 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800884
Tiger Huang8664f8c2018-10-11 19:14:35 +0800885 switch (expectedEventType) {
886 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800887 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
888 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000889 if (expectedFlags.has_value()) {
890 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
891 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800892 break;
893 }
894 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800895 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000896 assertMotionAction(expectedAction, motionEvent.getAction());
897
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000898 if (expectedFlags.has_value()) {
899 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
900 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800901 break;
902 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100903 case AINPUT_EVENT_TYPE_FOCUS: {
904 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
905 }
Prabir Pradhan99987712020-11-10 18:43:05 -0800906 case AINPUT_EVENT_TYPE_CAPTURE: {
907 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
908 }
Antonio Kantekf16f2832021-09-28 04:39:20 +0000909 case AINPUT_EVENT_TYPE_TOUCH_MODE: {
910 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
911 }
arthurhungb89ccb02020-12-30 16:19:01 +0800912 case AINPUT_EVENT_TYPE_DRAG: {
913 FAIL() << "Use 'consumeDragEvent' for DRAG events";
914 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800915 default: {
916 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
917 }
918 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800919 }
920
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100921 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
922 InputEvent* event = consume();
923 ASSERT_NE(nullptr, event) << mName.c_str()
924 << ": consumer should have returned non-NULL event.";
925 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
926 << "Got " << inputEventTypeToString(event->getType())
927 << " event instead of FOCUS event";
928
929 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
930 << mName.c_str() << ": event displayId should always be NONE.";
931
932 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
933 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100934 }
935
Prabir Pradhan99987712020-11-10 18:43:05 -0800936 void consumeCaptureEvent(bool hasCapture) {
937 const InputEvent* event = consume();
938 ASSERT_NE(nullptr, event) << mName.c_str()
939 << ": consumer should have returned non-NULL event.";
940 ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType())
941 << "Got " << inputEventTypeToString(event->getType())
942 << " event instead of CAPTURE event";
943
944 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
945 << mName.c_str() << ": event displayId should always be NONE.";
946
947 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
948 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
949 }
950
arthurhungb89ccb02020-12-30 16:19:01 +0800951 void consumeDragEvent(bool isExiting, float x, float y) {
952 const InputEvent* event = consume();
953 ASSERT_NE(nullptr, event) << mName.c_str()
954 << ": consumer should have returned non-NULL event.";
955 ASSERT_EQ(AINPUT_EVENT_TYPE_DRAG, event->getType())
956 << "Got " << inputEventTypeToString(event->getType())
957 << " event instead of DRAG event";
958
959 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
960 << mName.c_str() << ": event displayId should always be NONE.";
961
962 const auto& dragEvent = static_cast<const DragEvent&>(*event);
963 EXPECT_EQ(isExiting, dragEvent.isExiting());
964 EXPECT_EQ(x, dragEvent.getX());
965 EXPECT_EQ(y, dragEvent.getY());
966 }
967
Antonio Kantekf16f2832021-09-28 04:39:20 +0000968 void consumeTouchModeEvent(bool inTouchMode) {
969 const InputEvent* event = consume();
970 ASSERT_NE(nullptr, event) << mName.c_str()
971 << ": consumer should have returned non-NULL event.";
972 ASSERT_EQ(AINPUT_EVENT_TYPE_TOUCH_MODE, event->getType())
973 << "Got " << inputEventTypeToString(event->getType())
974 << " event instead of TOUCH_MODE event";
975
976 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
977 << mName.c_str() << ": event displayId should always be NONE.";
978 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
979 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
980 }
981
chaviwd1c23182019-12-20 18:44:56 -0800982 void assertNoEvents() {
983 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700984 if (event == nullptr) {
985 return;
986 }
987 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
988 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
989 ADD_FAILURE() << "Received key event "
990 << KeyEvent::actionToString(keyEvent.getAction());
991 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
992 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
993 ADD_FAILURE() << "Received motion event "
994 << MotionEvent::actionToString(motionEvent.getAction());
995 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
996 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
997 ADD_FAILURE() << "Received focus event, hasFocus = "
998 << (focusEvent.getHasFocus() ? "true" : "false");
Prabir Pradhan99987712020-11-10 18:43:05 -0800999 } else if (event->getType() == AINPUT_EVENT_TYPE_CAPTURE) {
1000 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1001 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1002 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Antonio Kantekf16f2832021-09-28 04:39:20 +00001003 } else if (event->getType() == AINPUT_EVENT_TYPE_TOUCH_MODE) {
1004 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1005 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1006 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001007 }
1008 FAIL() << mName.c_str()
1009 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001010 }
1011
1012 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1013
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001014 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1015
chaviwd1c23182019-12-20 18:44:56 -08001016protected:
1017 std::unique_ptr<InputConsumer> mConsumer;
1018 PreallocatedInputEventFactory mEventFactory;
1019
1020 std::string mName;
1021};
1022
chaviw3277faf2021-05-19 16:45:23 -05001023class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001024public:
1025 static const int32_t WIDTH = 600;
1026 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001027
Chris Yea209fde2020-07-22 13:54:51 -07001028 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001029 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001030 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001031 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001032 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001033 base::Result<std::unique_ptr<InputChannel>> channel =
1034 dispatcher->createInputChannel(name);
1035 token = (*channel)->getConnectionToken();
1036 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001037 }
1038
1039 inputApplicationHandle->updateInfo();
1040 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1041
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001042 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001043 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001044 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001045 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001046 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001047 mInfo.frameLeft = 0;
1048 mInfo.frameTop = 0;
1049 mInfo.frameRight = WIDTH;
1050 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001051 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001052 mInfo.globalScaleFactor = 1.0;
1053 mInfo.touchableRegion.clear();
1054 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001055 mInfo.ownerPid = WINDOW_PID;
1056 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001057 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001058 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001059 }
1060
Arthur Hungabbb9d82021-09-01 14:52:30 +00001061 sp<FakeWindowHandle> clone(
1062 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001063 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00001064 sp<FakeWindowHandle> handle =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001065 sp<FakeWindowHandle>::make(inputApplicationHandle, dispatcher,
1066 mInfo.name + "(Mirror)", displayId, mInfo.token);
Arthur Hungabbb9d82021-09-01 14:52:30 +00001067 return handle;
1068 }
1069
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001070 void setTouchable(bool touchable) {
1071 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1072 }
chaviwd1c23182019-12-20 18:44:56 -08001073
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001074 void setFocusable(bool focusable) {
1075 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1076 }
1077
1078 void setVisible(bool visible) {
1079 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1080 }
Vishnu Nair958da932020-08-21 17:12:37 -07001081
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001082 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001083 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001084 }
1085
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001086 void setPaused(bool paused) {
1087 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1088 }
1089
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001090 void setPreventSplitting(bool preventSplitting) {
1091 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001092 }
1093
1094 void setSlippery(bool slippery) {
1095 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1096 }
1097
1098 void setWatchOutsideTouch(bool watchOutside) {
1099 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1100 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001101
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001102 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1103
1104 void setInterceptsStylus(bool interceptsStylus) {
1105 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1106 }
1107
1108 void setDropInput(bool dropInput) {
1109 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1110 }
1111
1112 void setDropInputIfObscured(bool dropInputIfObscured) {
1113 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1114 }
1115
1116 void setNoInputChannel(bool noInputChannel) {
1117 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1118 }
1119
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001120 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1121
chaviw3277faf2021-05-19 16:45:23 -05001122 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001123
Bernardo Rufino7393d172021-02-26 13:56:11 +00001124 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1125
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001126 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001127 mInfo.frameLeft = frame.left;
1128 mInfo.frameTop = frame.top;
1129 mInfo.frameRight = frame.right;
1130 mInfo.frameBottom = frame.bottom;
1131 mInfo.touchableRegion.clear();
1132 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001133
1134 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1135 ui::Transform translate;
1136 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1137 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001138 }
1139
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001140 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1141
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001142 void setIsWallpaper(bool isWallpaper) {
1143 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1144 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001145
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001146 void setDupTouchToWallpaper(bool hasWallpaper) {
1147 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1148 }
chaviwd1c23182019-12-20 18:44:56 -08001149
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001150 void setTrustedOverlay(bool trustedOverlay) {
1151 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1152 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001153
chaviw9eaa22c2020-07-01 16:21:27 -07001154 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1155 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1156 }
1157
1158 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001159
yunho.shinf4a80b82020-11-16 21:13:57 +09001160 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1161
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001162 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1163 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1164 expectedFlags);
1165 }
1166
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001167 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1168 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
1169 }
1170
Svet Ganov5d3bc372020-01-26 23:11:07 -08001171 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001172 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -08001173 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
1174 expectedFlags);
1175 }
1176
1177 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001178 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -08001179 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
1180 expectedFlags);
1181 }
1182
1183 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001184 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001185 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1186 }
1187
1188 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1189 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001190 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
1191 expectedFlags);
1192 }
1193
Svet Ganov5d3bc372020-01-26 23:11:07 -08001194 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001195 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1196 int32_t expectedFlags = 0) {
1197 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1198 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001199 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1200 }
1201
1202 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001203 int32_t expectedFlags = 0) {
1204 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1205 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001206 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1207 }
1208
1209 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001210 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +00001211 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
1212 expectedFlags);
1213 }
1214
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001215 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1216 int32_t expectedFlags = 0) {
1217 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
1218 expectedFlags);
1219 }
1220
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001221 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1222 int32_t expectedFlags = 0) {
1223 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001224 ASSERT_NE(nullptr, event);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001225 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
1226 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1227 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1228 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1229 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1230 }
1231
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001232 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1233 ASSERT_NE(mInputReceiver, nullptr)
1234 << "Cannot consume events from a window with no receiver";
1235 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1236 }
1237
Prabir Pradhan99987712020-11-10 18:43:05 -08001238 void consumeCaptureEvent(bool hasCapture) {
1239 ASSERT_NE(mInputReceiver, nullptr)
1240 << "Cannot consume events from a window with no receiver";
1241 mInputReceiver->consumeCaptureEvent(hasCapture);
1242 }
1243
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001244 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1245 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001246 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001247 ASSERT_THAT(*motionEvent, matcher);
1248 }
1249
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001250 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
1251 std::optional<int32_t> expectedDisplayId,
1252 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001253 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1254 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1255 expectedFlags);
1256 }
1257
arthurhungb89ccb02020-12-30 16:19:01 +08001258 void consumeDragEvent(bool isExiting, float x, float y) {
1259 mInputReceiver->consumeDragEvent(isExiting, x, y);
1260 }
1261
Antonio Kantekf16f2832021-09-28 04:39:20 +00001262 void consumeTouchModeEvent(bool inTouchMode) {
1263 ASSERT_NE(mInputReceiver, nullptr)
1264 << "Cannot consume events from a window with no receiver";
1265 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1266 }
1267
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001268 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001269 if (mInputReceiver == nullptr) {
1270 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1271 return std::nullopt;
1272 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001273 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001274 }
1275
1276 void finishEvent(uint32_t sequenceNum) {
1277 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1278 mInputReceiver->finishEvent(sequenceNum);
1279 }
1280
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001281 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1282 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1283 mInputReceiver->sendTimeline(inputEventId, timeline);
1284 }
1285
chaviwaf87b3e2019-10-01 16:59:28 -07001286 InputEvent* consume() {
1287 if (mInputReceiver == nullptr) {
1288 return nullptr;
1289 }
1290 return mInputReceiver->consume();
1291 }
1292
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001293 MotionEvent* consumeMotion() {
1294 InputEvent* event = consume();
1295 if (event == nullptr) {
1296 ADD_FAILURE() << "Consume failed : no event";
1297 return nullptr;
1298 }
1299 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
1300 ADD_FAILURE() << "Instead of motion event, got "
1301 << inputEventTypeToString(event->getType());
1302 return nullptr;
1303 }
1304 return static_cast<MotionEvent*>(event);
1305 }
1306
Arthur Hungb92218b2018-08-14 12:00:21 +08001307 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001308 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001309 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001310 return; // Can't receive events if the window does not have input channel
1311 }
1312 ASSERT_NE(nullptr, mInputReceiver)
1313 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001314 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001315 }
1316
chaviwaf87b3e2019-10-01 16:59:28 -07001317 sp<IBinder> getToken() { return mInfo.token; }
1318
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001319 const std::string& getName() { return mName; }
1320
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001321 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1322 mInfo.ownerPid = ownerPid;
1323 mInfo.ownerUid = ownerUid;
1324 }
1325
Prabir Pradhanedd96402022-02-15 01:46:16 -08001326 int32_t getPid() const { return mInfo.ownerPid; }
1327
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001328 void destroyReceiver() { mInputReceiver = nullptr; }
1329
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001330 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1331
chaviwd1c23182019-12-20 18:44:56 -08001332private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001333 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001334 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001335 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001336};
1337
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001338std::atomic<int32_t> FakeWindowHandle::sId{1};
1339
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001340static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001341 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001342 int32_t displayId = ADISPLAY_ID_NONE,
1343 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001344 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001345 bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
1346 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001347 KeyEvent event;
1348 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1349
1350 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001351 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001352 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
1353 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001354
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001355 if (!allowKeyRepeat) {
1356 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1357 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001358 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001359 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001360}
1361
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001362static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001363 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001364 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
1365}
1366
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001367// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1368// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1369// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001370static InputEventInjectionResult injectKeyDownNoRepeat(
1371 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001372 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId,
1373 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
1374 /* allowKeyRepeat */ false);
1375}
1376
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001377static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001378 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001379 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
1380}
1381
Garfield Tandf26e862020-07-01 20:18:19 -07001382class PointerBuilder {
1383public:
1384 PointerBuilder(int32_t id, int32_t toolType) {
1385 mProperties.clear();
1386 mProperties.id = id;
1387 mProperties.toolType = toolType;
1388 mCoords.clear();
1389 }
1390
1391 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1392
1393 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1394
1395 PointerBuilder& axis(int32_t axis, float value) {
1396 mCoords.setAxisValue(axis, value);
1397 return *this;
1398 }
1399
1400 PointerProperties buildProperties() const { return mProperties; }
1401
1402 PointerCoords buildCoords() const { return mCoords; }
1403
1404private:
1405 PointerProperties mProperties;
1406 PointerCoords mCoords;
1407};
1408
1409class MotionEventBuilder {
1410public:
1411 MotionEventBuilder(int32_t action, int32_t source) {
1412 mAction = action;
1413 mSource = source;
1414 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1415 }
1416
1417 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1418 mEventTime = eventTime;
1419 return *this;
1420 }
1421
1422 MotionEventBuilder& displayId(int32_t displayId) {
1423 mDisplayId = displayId;
1424 return *this;
1425 }
1426
1427 MotionEventBuilder& actionButton(int32_t actionButton) {
1428 mActionButton = actionButton;
1429 return *this;
1430 }
1431
arthurhung6d4bed92021-03-17 11:59:33 +08001432 MotionEventBuilder& buttonState(int32_t buttonState) {
1433 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001434 return *this;
1435 }
1436
1437 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1438 mRawXCursorPosition = rawXCursorPosition;
1439 return *this;
1440 }
1441
1442 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1443 mRawYCursorPosition = rawYCursorPosition;
1444 return *this;
1445 }
1446
1447 MotionEventBuilder& pointer(PointerBuilder pointer) {
1448 mPointers.push_back(pointer);
1449 return *this;
1450 }
1451
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001452 MotionEventBuilder& addFlag(uint32_t flags) {
1453 mFlags |= flags;
1454 return *this;
1455 }
1456
Garfield Tandf26e862020-07-01 20:18:19 -07001457 MotionEvent build() {
1458 std::vector<PointerProperties> pointerProperties;
1459 std::vector<PointerCoords> pointerCoords;
1460 for (const PointerBuilder& pointer : mPointers) {
1461 pointerProperties.push_back(pointer.buildProperties());
1462 pointerCoords.push_back(pointer.buildCoords());
1463 }
1464
1465 // Set mouse cursor position for the most common cases to avoid boilerplate.
1466 if (mSource == AINPUT_SOURCE_MOUSE &&
1467 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1468 mPointers.size() == 1) {
1469 mRawXCursorPosition = pointerCoords[0].getX();
1470 mRawYCursorPosition = pointerCoords[0].getY();
1471 }
1472
1473 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001474 ui::Transform identityTransform;
Garfield Tandf26e862020-07-01 20:18:19 -07001475 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001476 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001477 mButtonState, MotionClassification::NONE, identityTransform,
1478 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07001479 mRawYCursorPosition, identityTransform, mEventTime, mEventTime,
1480 mPointers.size(), pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001481
1482 return event;
1483 }
1484
1485private:
1486 int32_t mAction;
1487 int32_t mSource;
1488 nsecs_t mEventTime;
1489 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1490 int32_t mActionButton{0};
1491 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001492 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001493 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1494 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1495
1496 std::vector<PointerBuilder> mPointers;
1497};
1498
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001499static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001500 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001501 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001502 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1503 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
1504 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1505 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001506}
1507
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001508static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001509 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001510 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001511 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001512 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1513 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001514 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001515 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
1516 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Garfield Tandf26e862020-07-01 20:18:19 -07001517 MotionEvent event = MotionEventBuilder(action, source)
1518 .displayId(displayId)
1519 .eventTime(eventTime)
1520 .rawXCursorPosition(cursorPosition.x)
1521 .rawYCursorPosition(cursorPosition.y)
1522 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1523 .x(position.x)
1524 .y(position.y))
1525 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001526
1527 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001528 return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode, targetUid,
1529 policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001530}
1531
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001532static InputEventInjectionResult injectMotionDown(
1533 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1534 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001535 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001536}
1537
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001538static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001539 int32_t source, int32_t displayId,
1540 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001541 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001542}
1543
Jackal Guof9696682018-10-05 12:23:23 +08001544static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1545 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1546 // Define a valid key event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001547 NotifyKeyArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1548 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1549 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001550
1551 return args;
1552}
1553
chaviwd1c23182019-12-20 18:44:56 -08001554static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1555 const std::vector<PointF>& points) {
1556 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001557 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1558 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1559 }
1560
chaviwd1c23182019-12-20 18:44:56 -08001561 PointerProperties pointerProperties[pointerCount];
1562 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001563
chaviwd1c23182019-12-20 18:44:56 -08001564 for (size_t i = 0; i < pointerCount; i++) {
1565 pointerProperties[i].clear();
1566 pointerProperties[i].id = i;
1567 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001568
chaviwd1c23182019-12-20 18:44:56 -08001569 pointerCoords[i].clear();
1570 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1571 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1572 }
Jackal Guof9696682018-10-05 12:23:23 +08001573
1574 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1575 // Define a valid motion event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001576 NotifyMotionArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001577 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1578 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001579 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1580 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001581 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1582 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001583
1584 return args;
1585}
1586
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001587static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1588 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1589}
1590
chaviwd1c23182019-12-20 18:44:56 -08001591static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1592 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1593}
1594
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001595static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1596 const PointerCaptureRequest& request) {
1597 return NotifyPointerCaptureChangedArgs(/* id */ 0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001598}
1599
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001600/**
1601 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1602 * broken channel.
1603 */
1604TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1605 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1606 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001607 sp<FakeWindowHandle>::make(application, mDispatcher,
1608 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001609
1610 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1611
1612 // Window closes its channel, but the window remains.
1613 window->destroyReceiver();
1614 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1615}
1616
Arthur Hungb92218b2018-08-14 12:00:21 +08001617TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001618 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001619 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1620 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001621
Arthur Hung72d8dc32020-03-28 00:48:39 +00001622 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001623 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1624 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1625 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001626
1627 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001628 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001629}
1630
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001631TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1632 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001633 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1634 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001635
1636 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1637 // Inject a MotionEvent to an unknown display.
1638 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1639 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1640 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1641
1642 // Window should receive motion event.
1643 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1644}
1645
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001646/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001647 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001648 * This test serves as a sanity check for the next test, where setInputWindows is
1649 * called twice.
1650 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001651TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001652 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001653 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1654 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001655 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001656
1657 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001658 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001659 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1660 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001661 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001662
1663 // Window should receive motion event.
1664 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1665}
1666
1667/**
1668 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001669 */
1670TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001671 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001672 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1673 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001674 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001675
1676 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1677 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001679 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1680 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001681 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001682
1683 // Window should receive motion event.
1684 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1685}
1686
Arthur Hungb92218b2018-08-14 12:00:21 +08001687// The foreground window should receive the first touch down event.
1688TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001689 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001690 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001691 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001692 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001693 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001694
Arthur Hung72d8dc32020-03-28 00:48:39 +00001695 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1697 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1698 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001699
1700 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001701 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001702 windowSecond->assertNoEvents();
1703}
1704
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001705/**
1706 * Two windows: A top window, and a wallpaper behind the window.
1707 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1708 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001709 * 1. foregroundWindow <-- dup touch to wallpaper
1710 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001711 */
1712TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1713 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1714 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001715 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001716 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001717 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001718 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001719 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001720 constexpr int expectedWallpaperFlags =
1721 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1722
1723 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1725 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1726 {100, 200}))
1727 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1728
1729 // Both foreground window and its wallpaper should receive the touch down
1730 foregroundWindow->consumeMotionDown();
1731 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1732
1733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1734 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1735 ADISPLAY_ID_DEFAULT, {110, 200}))
1736 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1737
1738 foregroundWindow->consumeMotionMove();
1739 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1740
1741 // Now the foreground window goes away, but the wallpaper stays
1742 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1743 foregroundWindow->consumeMotionCancel();
1744 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1745 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1746}
1747
1748/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001749 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1750 * with the following differences:
1751 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1752 * clean up the connection.
1753 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1754 * Ensure that there's no crash in the dispatcher.
1755 */
1756TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1757 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1758 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001759 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001760 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001761 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001762 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001763 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001764 constexpr int expectedWallpaperFlags =
1765 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1766
1767 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1769 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1770 {100, 200}))
1771 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1772
1773 // Both foreground window and its wallpaper should receive the touch down
1774 foregroundWindow->consumeMotionDown();
1775 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1776
1777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1778 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1779 ADISPLAY_ID_DEFAULT, {110, 200}))
1780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1781
1782 foregroundWindow->consumeMotionMove();
1783 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1784
1785 // Wallpaper closes its channel, but the window remains.
1786 wallpaperWindow->destroyReceiver();
1787 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1788
1789 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1790 // is no longer valid.
1791 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1792 foregroundWindow->consumeMotionCancel();
1793}
1794
1795/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001796 * A single window that receives touch (on top), and a wallpaper window underneath it.
1797 * The top window gets a multitouch gesture.
1798 * Ensure that wallpaper gets the same gesture.
1799 */
1800TEST_F(InputDispatcherTest, WallpaperWindow_ReceivesMultiTouch) {
1801 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1802 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001803 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001804 window->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001805
1806 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001807 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001808 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001809 constexpr int expectedWallpaperFlags =
1810 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1811
1812 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, wallpaperWindow}}});
1813
1814 // Touch down on top window
1815 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1816 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1817 {100, 100}))
1818 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1819
1820 // Both top window and its wallpaper should receive the touch down
1821 window->consumeMotionDown();
1822 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1823
1824 // Second finger down on the top window
1825 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001826 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001827 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1828 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1829 .x(100)
1830 .y(100))
1831 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1832 .x(150)
1833 .y(150))
1834 .build();
1835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1836 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1837 InputEventInjectionSync::WAIT_FOR_RESULT))
1838 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1839
1840 window->consumeMotionPointerDown(1 /* pointerIndex */);
1841 wallpaperWindow->consumeMotionPointerDown(1 /* pointerIndex */, ADISPLAY_ID_DEFAULT,
1842 expectedWallpaperFlags);
1843 window->assertNoEvents();
1844 wallpaperWindow->assertNoEvents();
1845}
1846
1847/**
1848 * Two windows: a window on the left and window on the right.
1849 * A third window, wallpaper, is behind both windows, and spans both top windows.
1850 * The first touch down goes to the left window. A second pointer touches down on the right window.
1851 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1852 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1853 * ACTION_POINTER_DOWN(1).
1854 */
1855TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1856 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1857 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001858 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001859 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001860 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001861
1862 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001863 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001864 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001865 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001866
1867 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001868 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001869 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001870 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001871 constexpr int expectedWallpaperFlags =
1872 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1873
1874 mDispatcher->setInputWindows(
1875 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1876
1877 // Touch down on left window
1878 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1879 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1880 {100, 100}))
1881 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1882
1883 // Both foreground window and its wallpaper should receive the touch down
1884 leftWindow->consumeMotionDown();
1885 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1886
1887 // Second finger down on the right window
1888 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001889 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001890 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1891 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1892 .x(100)
1893 .y(100))
1894 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1895 .x(300)
1896 .y(100))
1897 .build();
1898 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1899 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1900 InputEventInjectionSync::WAIT_FOR_RESULT))
1901 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1902
1903 leftWindow->consumeMotionMove();
1904 // Since the touch is split, right window gets ACTION_DOWN
1905 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1906 wallpaperWindow->consumeMotionPointerDown(1 /* pointerIndex */, ADISPLAY_ID_DEFAULT,
1907 expectedWallpaperFlags);
1908
1909 // Now, leftWindow, which received the first finger, disappears.
1910 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
1911 leftWindow->consumeMotionCancel();
1912 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1913 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1914
1915 // The pointer that's still down on the right window moves, and goes to the right window only.
1916 // As far as the dispatcher's concerned though, both pointers are still present.
1917 const MotionEvent secondFingerMoveEvent =
1918 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1919 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1920 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1921 .x(100)
1922 .y(100))
1923 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1924 .x(310)
1925 .y(110))
1926 .build();
1927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1928 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
1929 InputEventInjectionSync::WAIT_FOR_RESULT));
1930 rightWindow->consumeMotionMove();
1931
1932 leftWindow->assertNoEvents();
1933 rightWindow->assertNoEvents();
1934 wallpaperWindow->assertNoEvents();
1935}
1936
Arthur Hung74c248d2022-11-23 07:09:59 +00001937TEST_F(InputDispatcherTest, WallpaperWindowReceivesMultiTouch) {
1938 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1939 sp<FakeWindowHandle> window =
1940 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1941 window->setDupTouchToWallpaper(true);
1942
1943 sp<FakeWindowHandle> wallpaperWindow =
1944 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
1945 wallpaperWindow->setIsWallpaper(true);
1946 constexpr int expectedWallpaperFlags =
1947 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1948 wallpaperWindow->setPreventSplitting(true);
1949
1950 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, wallpaperWindow}}});
1951
1952 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1953 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1954 {50, 50}))
1955 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1956 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1957 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1958
1959 const MotionEvent secondFingerDownEvent =
1960 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1961 .displayId(ADISPLAY_ID_DEFAULT)
1962 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1963 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
1964 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
1965 .build();
1966 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1967 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1968 InputEventInjectionSync::WAIT_FOR_RESULT))
1969 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1970
1971 window->consumeMotionPointerDown(1);
1972 wallpaperWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1973
1974 const MotionEvent secondFingerUpEvent =
1975 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
1976 .displayId(ADISPLAY_ID_DEFAULT)
1977 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1978 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
1979 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
1980 .build();
1981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1982 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
1983 InputEventInjectionSync::WAIT_FOR_RESULT))
1984 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1985 window->consumeMotionPointerUp(1);
1986 wallpaperWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1987
1988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1989 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
1990 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1991 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1992 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1993}
1994
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001995/**
1996 * On the display, have a single window, and also an area where there's no window.
1997 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
1998 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
1999 */
2000TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2001 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2002 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002003 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002004
2005 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
2006 NotifyMotionArgs args;
2007
2008 // Touch down on the empty space
2009 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}})));
2010
2011 mDispatcher->waitForIdle();
2012 window->assertNoEvents();
2013
2014 // Now touch down on the window with another pointer
2015 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}})));
2016 mDispatcher->waitForIdle();
2017 window->consumeMotionDown();
2018}
2019
2020/**
2021 * Same test as above, but instead of touching the empty space, the first touch goes to
2022 * non-touchable window.
2023 */
2024TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2025 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2026 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002027 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002028 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2029 window1->setTouchable(false);
2030 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002031 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002032 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2033
2034 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2035
2036 NotifyMotionArgs args;
2037 // Touch down on the non-touchable window
2038 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})));
2039
2040 mDispatcher->waitForIdle();
2041 window1->assertNoEvents();
2042 window2->assertNoEvents();
2043
2044 // Now touch down on the window with another pointer
2045 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
2046 mDispatcher->waitForIdle();
2047 window2->consumeMotionDown();
2048}
2049
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002050/**
2051 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2052 * to the event time of the first ACTION_DOWN sent to the particular window.
2053 */
2054TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2055 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2056 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002057 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002058 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2059 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002060 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002061 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2062
2063 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2064
2065 NotifyMotionArgs args;
2066 // Touch down on the first window
2067 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})));
2068
2069 mDispatcher->waitForIdle();
2070 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002071 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002072 window2->assertNoEvents();
2073 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
2074 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
2075 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
2076
2077 // Now touch down on the window with another pointer
2078 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
2079 mDispatcher->waitForIdle();
2080 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002081 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002082 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
2083 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
2084 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
2085 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
2086
2087 // Now move the pointer on the second window
2088 mDispatcher->notifyMotion(
2089 &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}})));
2090 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002091 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002092
2093 // Now add new touch down on the second window
2094 mDispatcher->notifyMotion(
2095 &(args = generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}})));
2096 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002097 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002098
2099 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
2100 window1->consumeMotionMove();
2101 window1->assertNoEvents();
2102
2103 // Now move the pointer on the first window
2104 mDispatcher->notifyMotion(
2105 &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}})));
2106 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002107 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002108
2109 mDispatcher->notifyMotion(&(
2110 args = generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}})));
2111 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002112 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002113}
2114
Garfield Tandf26e862020-07-01 20:18:19 -07002115TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07002116 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07002117 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002118 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002119 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002120 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002121 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002122 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002123
2124 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2125
2126 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
2127
2128 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002129 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002130 injectMotionEvent(mDispatcher,
2131 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2132 AINPUT_SOURCE_MOUSE)
2133 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2134 .x(900)
2135 .y(400))
2136 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002137 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07002138
2139 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002140 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002141 injectMotionEvent(mDispatcher,
2142 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2143 AINPUT_SOURCE_MOUSE)
2144 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2145 .x(300)
2146 .y(400))
2147 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002148 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2149 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07002150
2151 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002152 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002153 injectMotionEvent(mDispatcher,
2154 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2155 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2156 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2157 .x(300)
2158 .y(400))
2159 .build()));
2160 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2161
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002162 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002163 injectMotionEvent(mDispatcher,
2164 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
2165 AINPUT_SOURCE_MOUSE)
2166 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2167 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2168 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2169 .x(300)
2170 .y(400))
2171 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002172 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07002173
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002175 injectMotionEvent(mDispatcher,
2176 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
2177 AINPUT_SOURCE_MOUSE)
2178 .buttonState(0)
2179 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2180 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2181 .x(300)
2182 .y(400))
2183 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002184 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07002185
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002186 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002187 injectMotionEvent(mDispatcher,
2188 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
2189 .buttonState(0)
2190 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2191 .x(300)
2192 .y(400))
2193 .build()));
2194 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2195
2196 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002198 injectMotionEvent(mDispatcher,
2199 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2200 AINPUT_SOURCE_MOUSE)
2201 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2202 .x(900)
2203 .y(400))
2204 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002205 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2206 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002207
2208 // No more events
2209 windowLeft->assertNoEvents();
2210 windowRight->assertNoEvents();
2211}
2212
2213TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
2214 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2215
2216 sp<FakeWindowHandle> spyWindow =
2217 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2218 spyWindow->setFrame(Rect(0, 0, 600, 800));
2219 spyWindow->setTrustedOverlay(true);
2220 spyWindow->setSpy(true);
2221 sp<FakeWindowHandle> window =
2222 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2223 window->setFrame(Rect(0, 0, 600, 800));
2224
2225 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2226 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2227
2228 // Send mouse cursor to the window
2229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2230 injectMotionEvent(mDispatcher,
2231 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2232 AINPUT_SOURCE_MOUSE)
2233 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2234 .x(100)
2235 .y(100))
2236 .build()));
2237
2238 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2239 WithSource(AINPUT_SOURCE_MOUSE)));
2240 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2241 WithSource(AINPUT_SOURCE_MOUSE)));
2242
2243 window->assertNoEvents();
2244 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07002245}
2246
2247// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
2248// directly in this test.
2249TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07002250 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07002251 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002252 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002253 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002254
2255 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2256
2257 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2258
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002260 injectMotionEvent(mDispatcher,
2261 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2262 AINPUT_SOURCE_MOUSE)
2263 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2264 .x(300)
2265 .y(400))
2266 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002267 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07002268 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002270 injectMotionEvent(mDispatcher,
2271 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2272 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2273 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2274 .x(300)
2275 .y(400))
2276 .build()));
2277 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2278
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002279 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002280 injectMotionEvent(mDispatcher,
2281 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
2282 AINPUT_SOURCE_MOUSE)
2283 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2284 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2285 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2286 .x(300)
2287 .y(400))
2288 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002289 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07002290
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002291 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002292 injectMotionEvent(mDispatcher,
2293 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
2294 AINPUT_SOURCE_MOUSE)
2295 .buttonState(0)
2296 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2297 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2298 .x(300)
2299 .y(400))
2300 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002301 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07002302
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002303 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002304 injectMotionEvent(mDispatcher,
2305 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
2306 .buttonState(0)
2307 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2308 .x(300)
2309 .y(400))
2310 .build()));
2311 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2312
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002314 injectMotionEvent(mDispatcher,
2315 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
2316 AINPUT_SOURCE_MOUSE)
2317 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2318 .x(300)
2319 .y(400))
2320 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002321 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
Garfield Tandf26e862020-07-01 20:18:19 -07002322}
2323
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08002324/**
Siarhei Vishniakoud57302f2022-11-08 11:12:29 -08002325 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
2326 * is generated.
2327 */
2328TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
2329 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2330 sp<FakeWindowHandle> window =
2331 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2332 window->setFrame(Rect(0, 0, 1200, 800));
2333
2334 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2335
2336 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2337
2338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2339 injectMotionEvent(mDispatcher,
2340 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2341 AINPUT_SOURCE_MOUSE)
2342 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2343 .x(300)
2344 .y(400))
2345 .build()));
2346 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2347
2348 // Remove the window, but keep the channel.
2349 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
2350 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2351}
2352
2353/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08002354 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoud57302f2022-11-08 11:12:29 -08002355 * The tap causes a HOVER_EXIT event to be generated because the current event
2356 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08002357 */
2358TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
2359 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2360 sp<FakeWindowHandle> window =
2361 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2362 window->setFrame(Rect(0, 0, 100, 100));
2363
2364 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2365
2366 // Inject a hover_move from mouse.
2367 NotifyMotionArgs motionArgs =
2368 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
2369 ADISPLAY_ID_DEFAULT, {{50, 50}});
2370 motionArgs.xCursorPosition = 50;
2371 motionArgs.yCursorPosition = 50;
2372 mDispatcher->notifyMotion(&motionArgs);
2373 ASSERT_NO_FATAL_FAILURE(
2374 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2375 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08002376
2377 // Tap on the window
2378 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2379 ADISPLAY_ID_DEFAULT, {{10, 10}});
2380 mDispatcher->notifyMotion(&motionArgs);
2381 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoud57302f2022-11-08 11:12:29 -08002382 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2383 WithSource(AINPUT_SOURCE_MOUSE))));
2384
2385 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08002386 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
2387 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
2388
2389 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2390 ADISPLAY_ID_DEFAULT, {{10, 10}});
2391 mDispatcher->notifyMotion(&motionArgs);
2392 ASSERT_NO_FATAL_FAILURE(
2393 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
2394 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
2395}
2396
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02002397TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
2398 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2399 sp<FakeWindowHandle> windowDefaultDisplay =
2400 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
2401 ADISPLAY_ID_DEFAULT);
2402 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
2403 sp<FakeWindowHandle> windowSecondDisplay =
2404 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
2405 SECOND_DISPLAY_ID);
2406 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
2407
2408 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
2409 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
2410
2411 // Set cursor position in window in default display and check that hover enter and move
2412 // events are generated.
2413 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2414 injectMotionEvent(mDispatcher,
2415 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2416 AINPUT_SOURCE_MOUSE)
2417 .displayId(ADISPLAY_ID_DEFAULT)
2418 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2419 .x(300)
2420 .y(600))
2421 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002422 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02002423
2424 // Remove all windows in secondary display and check that no event happens on window in
2425 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002426 mDispatcher->setInputWindows(
2427 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02002428 windowDefaultDisplay->assertNoEvents();
2429
2430 // Move cursor position in window in default display and check that only hover move
2431 // event is generated and not hover enter event.
2432 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
2433 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
2434 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2435 injectMotionEvent(mDispatcher,
2436 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2437 AINPUT_SOURCE_MOUSE)
2438 .displayId(ADISPLAY_ID_DEFAULT)
2439 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2440 .x(400)
2441 .y(700))
2442 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002443 windowDefaultDisplay->consumeMotionEvent(
2444 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2445 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02002446 windowDefaultDisplay->assertNoEvents();
2447}
2448
Garfield Tan00f511d2019-06-12 16:55:40 -07002449TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07002450 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07002451
2452 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002453 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07002454 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07002455 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002456 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07002457 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07002458
2459 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2460
Arthur Hung72d8dc32020-03-28 00:48:39 +00002461 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07002462
2463 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
2464 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07002466 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002467 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002468 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07002469 windowRight->assertNoEvents();
2470}
2471
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002472TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07002473 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002474 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2475 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07002476 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002477
Arthur Hung72d8dc32020-03-28 00:48:39 +00002478 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002479 setFocusedWindow(window);
2480
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002481 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002482
2483 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2484 mDispatcher->notifyKey(&keyArgs);
2485
2486 // Window should receive key down event.
2487 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2488
2489 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
2490 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002491 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002492 mDispatcher->notifyDeviceReset(&args);
2493 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
2494 AKEY_EVENT_FLAG_CANCELED);
2495}
2496
2497TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07002498 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002499 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2500 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002501
Arthur Hung72d8dc32020-03-28 00:48:39 +00002502 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002503
2504 NotifyMotionArgs motionArgs =
2505 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2506 ADISPLAY_ID_DEFAULT);
2507 mDispatcher->notifyMotion(&motionArgs);
2508
2509 // Window should receive motion down event.
2510 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2511
2512 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
2513 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002514 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002515 mDispatcher->notifyDeviceReset(&args);
2516 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
2517 0 /*expectedFlags*/);
2518}
2519
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08002520TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
2521 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002522 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2523 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08002524 window->setFocusable(true);
2525
2526 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2527 setFocusedWindow(window);
2528
2529 window->consumeFocusEvent(true);
2530
2531 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2532 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
2533 const nsecs_t injectTime = keyArgs.eventTime;
2534 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
2535 mDispatcher->notifyKey(&keyArgs);
2536 // The dispatching time should be always greater than or equal to intercept key timeout.
2537 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2538 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
2539 std::chrono::nanoseconds(interceptKeyTimeout).count());
2540}
2541
2542TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
2543 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002544 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2545 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08002546 window->setFocusable(true);
2547
2548 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2549 setFocusedWindow(window);
2550
2551 window->consumeFocusEvent(true);
2552
2553 NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2554 NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
2555 mFakePolicy->setInterceptKeyTimeout(150ms);
2556 mDispatcher->notifyKey(&keyDown);
2557 mDispatcher->notifyKey(&keyUp);
2558
2559 // Window should receive key event immediately when same key up.
2560 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2561 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
2562}
2563
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002564/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002565 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
2566 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
2567 * ACTION_OUTSIDE event is sent per gesture.
2568 */
2569TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
2570 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
2571 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002572 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2573 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002574 window->setWatchOutsideTouch(true);
2575 window->setFrame(Rect{0, 0, 100, 100});
2576 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002577 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
2578 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002579 secondWindow->setFrame(Rect{100, 100, 200, 200});
2580 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002581 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
2582 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002583 thirdWindow->setFrame(Rect{200, 200, 300, 300});
2584 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
2585
2586 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
2587 NotifyMotionArgs motionArgs =
2588 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2589 ADISPLAY_ID_DEFAULT, {PointF{-10, -10}});
2590 mDispatcher->notifyMotion(&motionArgs);
2591 window->assertNoEvents();
2592 secondWindow->assertNoEvents();
2593
2594 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
2595 // Now, `window` should get ACTION_OUTSIDE.
2596 motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2597 {PointF{-10, -10}, PointF{105, 105}});
2598 mDispatcher->notifyMotion(&motionArgs);
2599 window->consumeMotionOutside();
2600 secondWindow->consumeMotionDown();
2601 thirdWindow->assertNoEvents();
2602
2603 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
2604 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
2605 motionArgs = generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2606 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}});
2607 mDispatcher->notifyMotion(&motionArgs);
2608 window->assertNoEvents();
2609 secondWindow->consumeMotionMove();
2610 thirdWindow->consumeMotionDown();
2611}
2612
Prabir Pradhan814fe082022-07-22 20:22:18 +00002613TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
2614 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002615 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2616 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00002617 window->setFocusable(true);
2618
2619 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
2620 setFocusedWindow(window);
2621
2622 window->consumeFocusEvent(true);
2623
2624 NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2625 NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
2626 mDispatcher->notifyKey(&keyDown);
2627 mDispatcher->notifyKey(&keyUp);
2628
2629 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2630 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
2631
2632 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
2633 mDispatcher->onWindowInfosChanged({}, {});
2634
2635 window->consumeFocusEvent(false);
2636
2637 mDispatcher->notifyKey(&keyDown);
2638 mDispatcher->notifyKey(&keyUp);
2639 window->assertNoEvents();
2640}
2641
Arthur Hung96483742022-11-15 03:30:48 +00002642TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
2643 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2644 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2645 "Fake Window", ADISPLAY_ID_DEFAULT);
2646 // Ensure window is non-split and have some transform.
2647 window->setPreventSplitting(true);
2648 window->setWindowOffset(20, 40);
2649 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
2650
2651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2652 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2653 {50, 50}))
2654 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2655 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2656
2657 const MotionEvent secondFingerDownEvent =
2658 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2659 .displayId(ADISPLAY_ID_DEFAULT)
2660 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
2661 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
2662 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
2663 .x(-30)
2664 .y(-50))
2665 .build();
2666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2667 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2668 InputEventInjectionSync::WAIT_FOR_RESULT))
2669 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2670
2671 const MotionEvent* event = window->consumeMotion();
2672 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
2673 EXPECT_EQ(70, event->getX(0)); // 50 + 20
2674 EXPECT_EQ(90, event->getY(0)); // 50 + 40
2675 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
2676 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
2677}
2678
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002679/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002680 * Ensure the correct coordinate spaces are used by InputDispatcher.
2681 *
2682 * InputDispatcher works in the display space, so its coordinate system is relative to the display
2683 * panel. Windows get events in the window space, and get raw coordinates in the logical display
2684 * space.
2685 */
2686class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
2687public:
2688 void SetUp() override {
2689 InputDispatcherTest::SetUp();
2690 mDisplayInfos.clear();
2691 mWindowInfos.clear();
2692 }
2693
2694 void addDisplayInfo(int displayId, const ui::Transform& transform) {
2695 gui::DisplayInfo info;
2696 info.displayId = displayId;
2697 info.transform = transform;
2698 mDisplayInfos.push_back(std::move(info));
2699 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
2700 }
2701
2702 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
2703 mWindowInfos.push_back(*windowHandle->getInfo());
2704 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
2705 }
2706
2707 // Set up a test scenario where the display has a scaled projection and there are two windows
2708 // on the display.
2709 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
2710 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
2711 // respectively.
2712 ui::Transform displayTransform;
2713 displayTransform.set(2, 0, 0, 4);
2714 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
2715
2716 std::shared_ptr<FakeApplicationHandle> application =
2717 std::make_shared<FakeApplicationHandle>();
2718
2719 // Add two windows to the display. Their frames are represented in the display space.
2720 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002721 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
2722 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002723 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
2724 addWindow(firstWindow);
2725
2726 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002727 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
2728 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002729 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
2730 addWindow(secondWindow);
2731 return {std::move(firstWindow), std::move(secondWindow)};
2732 }
2733
2734private:
2735 std::vector<gui::DisplayInfo> mDisplayInfos;
2736 std::vector<gui::WindowInfo> mWindowInfos;
2737};
2738
2739TEST_F(InputDispatcherDisplayProjectionTest, HitTestsInDisplaySpace) {
2740 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2741 // Send down to the first window. The point is represented in the display space. The point is
2742 // selected so that if the hit test was done with the transform applied to it, then it would
2743 // end up in the incorrect window.
2744 NotifyMotionArgs downMotionArgs =
2745 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2746 ADISPLAY_ID_DEFAULT, {PointF{75, 55}});
2747 mDispatcher->notifyMotion(&downMotionArgs);
2748
2749 firstWindow->consumeMotionDown();
2750 secondWindow->assertNoEvents();
2751}
2752
2753// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
2754// the event should be treated as being in the logical display space.
2755TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
2756 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2757 // Send down to the first window. The point is represented in the logical display space. The
2758 // point is selected so that if the hit test was done in logical display space, then it would
2759 // end up in the incorrect window.
2760 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2761 PointF{75 * 2, 55 * 4});
2762
2763 firstWindow->consumeMotionDown();
2764 secondWindow->assertNoEvents();
2765}
2766
Prabir Pradhandaa2f142021-12-10 09:30:08 +00002767// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
2768// event should be treated as being in the logical display space.
2769TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
2770 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2771
2772 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
2773 ui::Transform injectedEventTransform;
2774 injectedEventTransform.set(matrix);
2775 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
2776 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
2777
2778 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2779 .displayId(ADISPLAY_ID_DEFAULT)
2780 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
2781 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2782 .x(untransformedPoint.x)
2783 .y(untransformedPoint.y))
2784 .build();
2785 event.transform(matrix);
2786
2787 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
2788 InputEventInjectionSync::WAIT_FOR_RESULT);
2789
2790 firstWindow->consumeMotionDown();
2791 secondWindow->assertNoEvents();
2792}
2793
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002794TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
2795 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2796
2797 // Send down to the second window.
2798 NotifyMotionArgs downMotionArgs =
2799 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2800 ADISPLAY_ID_DEFAULT, {PointF{150, 220}});
2801 mDispatcher->notifyMotion(&downMotionArgs);
2802
2803 firstWindow->assertNoEvents();
2804 const MotionEvent* event = secondWindow->consumeMotion();
2805 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
2806
2807 // Ensure that the events from the "getRaw" API are in logical display coordinates.
2808 EXPECT_EQ(300, event->getRawX(0));
2809 EXPECT_EQ(880, event->getRawY(0));
2810
2811 // Ensure that the x and y values are in the window's coordinate space.
2812 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
2813 // the logical display space. This will be the origin of the window space.
2814 EXPECT_EQ(100, event->getX(0));
2815 EXPECT_EQ(80, event->getY(0));
2816}
2817
Siarhei Vishniakou18050092021-09-01 13:32:49 -07002818using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
2819 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002820
2821class TransferTouchFixture : public InputDispatcherTest,
2822 public ::testing::WithParamInterface<TransferFunction> {};
2823
2824TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07002825 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08002826
2827 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002828 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002829 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
2830 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002831 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002832 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
2833 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002834
2835 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00002836 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002837
2838 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002839 NotifyMotionArgs downMotionArgs =
2840 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2841 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002842 mDispatcher->notifyMotion(&downMotionArgs);
2843 // Only the first window should get the down event
2844 firstWindow->consumeMotionDown();
2845 secondWindow->assertNoEvents();
2846
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002847 // Transfer touch to the second window
2848 TransferFunction f = GetParam();
2849 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
2850 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002851 // The first window gets cancel and the second gets down
2852 firstWindow->consumeMotionCancel();
2853 secondWindow->consumeMotionDown();
2854
2855 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002856 NotifyMotionArgs upMotionArgs =
2857 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2858 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002859 mDispatcher->notifyMotion(&upMotionArgs);
2860 // The first window gets no events and the second gets up
2861 firstWindow->assertNoEvents();
2862 secondWindow->consumeMotionUp();
2863}
2864
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07002865/**
2866 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
2867 * from. When we have spy windows, there are several windows to choose from: either spy, or the
2868 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
2869 * natural to the user.
2870 * In this test, we are sending a pointer to both spy window and first window. We then try to
2871 * transfer touch to the second window. The dispatcher should identify the first window as the
2872 * one that should lose the gesture, and therefore the action should be to move the gesture from
2873 * the first window to the second.
2874 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
2875 * the other API, as well.
2876 */
2877TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
2878 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2879
2880 // Create a couple of windows + a spy window
2881 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002882 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07002883 spyWindow->setTrustedOverlay(true);
2884 spyWindow->setSpy(true);
2885 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002886 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07002887 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002888 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07002889
2890 // Add the windows to the dispatcher
2891 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
2892
2893 // Send down to the first window
2894 NotifyMotionArgs downMotionArgs =
2895 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2896 ADISPLAY_ID_DEFAULT);
2897 mDispatcher->notifyMotion(&downMotionArgs);
2898 // Only the first window and spy should get the down event
2899 spyWindow->consumeMotionDown();
2900 firstWindow->consumeMotionDown();
2901
2902 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
2903 // if f === 'transferTouch'.
2904 TransferFunction f = GetParam();
2905 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
2906 ASSERT_TRUE(success);
2907 // The first window gets cancel and the second gets down
2908 firstWindow->consumeMotionCancel();
2909 secondWindow->consumeMotionDown();
2910
2911 // Send up event to the second window
2912 NotifyMotionArgs upMotionArgs =
2913 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2914 ADISPLAY_ID_DEFAULT);
2915 mDispatcher->notifyMotion(&upMotionArgs);
2916 // The first window gets no events and the second+spy get up
2917 firstWindow->assertNoEvents();
2918 spyWindow->consumeMotionUp();
2919 secondWindow->consumeMotionUp();
2920}
2921
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002922TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07002923 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08002924
2925 PointF touchPoint = {10, 10};
2926
2927 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002928 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002929 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
2930 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08002931 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002932 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002933 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
2934 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08002935 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002936
2937 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00002938 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002939
2940 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002941 NotifyMotionArgs downMotionArgs =
2942 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2943 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002944 mDispatcher->notifyMotion(&downMotionArgs);
2945 // Only the first window should get the down event
2946 firstWindow->consumeMotionDown();
2947 secondWindow->assertNoEvents();
2948
2949 // Send pointer down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002950 NotifyMotionArgs pointerDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002951 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002952 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002953 mDispatcher->notifyMotion(&pointerDownMotionArgs);
2954 // Only the first window should get the pointer down event
2955 firstWindow->consumeMotionPointerDown(1);
2956 secondWindow->assertNoEvents();
2957
2958 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002959 TransferFunction f = GetParam();
2960 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
2961 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002962 // The first window gets cancel and the second gets down and pointer down
2963 firstWindow->consumeMotionCancel();
2964 secondWindow->consumeMotionDown();
2965 secondWindow->consumeMotionPointerDown(1);
2966
2967 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002968 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002969 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002970 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002971 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2972 // The first window gets nothing and the second gets pointer up
2973 firstWindow->assertNoEvents();
2974 secondWindow->consumeMotionPointerUp(1);
2975
2976 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002977 NotifyMotionArgs upMotionArgs =
2978 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2979 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002980 mDispatcher->notifyMotion(&upMotionArgs);
2981 // The first window gets nothing and the second gets up
2982 firstWindow->assertNoEvents();
2983 secondWindow->consumeMotionUp();
2984}
2985
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002986// For the cases of single pointer touch and two pointers non-split touch, the api's
2987// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
2988// for the case where there are multiple pointers split across several windows.
2989INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
2990 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07002991 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
2992 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07002993 return dispatcher->transferTouch(destChannelToken,
2994 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002995 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07002996 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
2997 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002998 return dispatcher->transferTouchFocus(from, to,
2999 false /*isDragAndDrop*/);
3000 }));
3001
Svet Ganov5d3bc372020-01-26 23:11:07 -08003002TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07003003 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08003004
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003005 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003006 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3007 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003008 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08003009
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003010 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003011 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3012 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003013 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08003014
3015 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00003016 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003017
3018 PointF pointInFirst = {300, 200};
3019 PointF pointInSecond = {300, 600};
3020
3021 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003022 NotifyMotionArgs firstDownMotionArgs =
3023 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3024 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003025 mDispatcher->notifyMotion(&firstDownMotionArgs);
3026 // Only the first window should get the down event
3027 firstWindow->consumeMotionDown();
3028 secondWindow->assertNoEvents();
3029
3030 // Send down to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003031 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003032 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003033 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003034 mDispatcher->notifyMotion(&secondDownMotionArgs);
3035 // The first window gets a move and the second a down
3036 firstWindow->consumeMotionMove();
3037 secondWindow->consumeMotionDown();
3038
3039 // Transfer touch focus to the second window
3040 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
3041 // The first window gets cancel and the new gets pointer down (it already saw down)
3042 firstWindow->consumeMotionCancel();
3043 secondWindow->consumeMotionPointerDown(1);
3044
3045 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003046 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003047 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003048 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003049 mDispatcher->notifyMotion(&pointerUpMotionArgs);
3050 // The first window gets nothing and the second gets pointer up
3051 firstWindow->assertNoEvents();
3052 secondWindow->consumeMotionPointerUp(1);
3053
3054 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003055 NotifyMotionArgs upMotionArgs =
3056 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3057 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003058 mDispatcher->notifyMotion(&upMotionArgs);
3059 // The first window gets nothing and the second gets up
3060 firstWindow->assertNoEvents();
3061 secondWindow->consumeMotionUp();
3062}
3063
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003064// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
3065// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
3066// touch is not supported, so the touch should continue on those windows and the transferred-to
3067// window should get nothing.
3068TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
3069 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3070
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003071 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003072 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3073 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003074 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003075
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003076 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003077 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3078 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003079 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003080
3081 // Add the windows to the dispatcher
3082 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
3083
3084 PointF pointInFirst = {300, 200};
3085 PointF pointInSecond = {300, 600};
3086
3087 // Send down to the first window
3088 NotifyMotionArgs firstDownMotionArgs =
3089 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3090 ADISPLAY_ID_DEFAULT, {pointInFirst});
3091 mDispatcher->notifyMotion(&firstDownMotionArgs);
3092 // Only the first window should get the down event
3093 firstWindow->consumeMotionDown();
3094 secondWindow->assertNoEvents();
3095
3096 // Send down to the second window
3097 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003098 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003099 {pointInFirst, pointInSecond});
3100 mDispatcher->notifyMotion(&secondDownMotionArgs);
3101 // The first window gets a move and the second a down
3102 firstWindow->consumeMotionMove();
3103 secondWindow->consumeMotionDown();
3104
3105 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07003106 const bool transferred =
3107 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003108 // The 'transferTouch' call should not succeed, because there are 2 touched windows
3109 ASSERT_FALSE(transferred);
3110 firstWindow->assertNoEvents();
3111 secondWindow->assertNoEvents();
3112
3113 // The rest of the dispatch should proceed as normal
3114 // Send pointer up to the second window
3115 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003116 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003117 {pointInFirst, pointInSecond});
3118 mDispatcher->notifyMotion(&pointerUpMotionArgs);
3119 // The first window gets MOVE and the second gets pointer up
3120 firstWindow->consumeMotionMove();
3121 secondWindow->consumeMotionUp();
3122
3123 // Send up event to the first window
3124 NotifyMotionArgs upMotionArgs =
3125 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3126 ADISPLAY_ID_DEFAULT);
3127 mDispatcher->notifyMotion(&upMotionArgs);
3128 // The first window gets nothing and the second gets up
3129 firstWindow->consumeMotionUp();
3130 secondWindow->assertNoEvents();
3131}
3132
Arthur Hungabbb9d82021-09-01 14:52:30 +00003133// This case will create two windows and one mirrored window on the default display and mirror
3134// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
3135// the windows info of second display before default display.
3136TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
3137 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3138 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003139 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00003140 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003141 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003142 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00003143 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003144
3145 sp<FakeWindowHandle> mirrorWindowInPrimary =
3146 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
3147 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003148
3149 sp<FakeWindowHandle> firstWindowInSecondary =
3150 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
3151 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003152
3153 sp<FakeWindowHandle> secondWindowInSecondary =
3154 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
3155 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003156
3157 // Update window info, let it find window handle of second display first.
3158 mDispatcher->setInputWindows(
3159 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
3160 {ADISPLAY_ID_DEFAULT,
3161 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
3162
3163 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3164 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3165 {50, 50}))
3166 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3167
3168 // Window should receive motion event.
3169 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3170
3171 // Transfer touch focus
3172 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
3173 secondWindowInPrimary->getToken()));
3174 // The first window gets cancel.
3175 firstWindowInPrimary->consumeMotionCancel();
3176 secondWindowInPrimary->consumeMotionDown();
3177
3178 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3179 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3180 ADISPLAY_ID_DEFAULT, {150, 50}))
3181 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3182 firstWindowInPrimary->assertNoEvents();
3183 secondWindowInPrimary->consumeMotionMove();
3184
3185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3186 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3187 {150, 50}))
3188 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3189 firstWindowInPrimary->assertNoEvents();
3190 secondWindowInPrimary->consumeMotionUp();
3191}
3192
3193// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
3194// 'transferTouch' api.
3195TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
3196 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3197 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003198 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00003199 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003200 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003201 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00003202 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003203
3204 sp<FakeWindowHandle> mirrorWindowInPrimary =
3205 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
3206 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003207
3208 sp<FakeWindowHandle> firstWindowInSecondary =
3209 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
3210 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003211
3212 sp<FakeWindowHandle> secondWindowInSecondary =
3213 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
3214 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003215
3216 // Update window info, let it find window handle of second display first.
3217 mDispatcher->setInputWindows(
3218 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
3219 {ADISPLAY_ID_DEFAULT,
3220 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
3221
3222 // Touch on second display.
3223 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3224 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
3225 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3226
3227 // Window should receive motion event.
3228 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
3229
3230 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07003231 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003232
3233 // The first window gets cancel.
3234 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
3235 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
3236
3237 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3238 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3239 SECOND_DISPLAY_ID, {150, 50}))
3240 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3241 firstWindowInPrimary->assertNoEvents();
3242 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
3243
3244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3245 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
3246 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3247 firstWindowInPrimary->assertNoEvents();
3248 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
3249}
3250
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003251TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003252 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003253 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3254 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003255
Vishnu Nair47074b82020-08-14 11:54:47 -07003256 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003257 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003258 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003259
3260 window->consumeFocusEvent(true);
3261
3262 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3263 mDispatcher->notifyKey(&keyArgs);
3264
3265 // Window should receive key down event.
3266 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3267}
3268
3269TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003270 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003271 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3272 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003273
Arthur Hung72d8dc32020-03-28 00:48:39 +00003274 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003275
3276 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3277 mDispatcher->notifyKey(&keyArgs);
3278 mDispatcher->waitForIdle();
3279
3280 window->assertNoEvents();
3281}
3282
3283// If a window is touchable, but does not have focus, it should receive motion events, but not keys
3284TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07003285 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003286 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3287 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003288
Arthur Hung72d8dc32020-03-28 00:48:39 +00003289 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003290
3291 // Send key
3292 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3293 mDispatcher->notifyKey(&keyArgs);
3294 // Send motion
3295 NotifyMotionArgs motionArgs =
3296 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3297 ADISPLAY_ID_DEFAULT);
3298 mDispatcher->notifyMotion(&motionArgs);
3299
3300 // Window should receive only the motion event
3301 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3302 window->assertNoEvents(); // Key event or focus event will not be received
3303}
3304
arthurhungea3f4fc2020-12-21 23:18:53 +08003305TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
3306 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3307
arthurhungea3f4fc2020-12-21 23:18:53 +08003308 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003309 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3310 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08003311 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08003312
arthurhungea3f4fc2020-12-21 23:18:53 +08003313 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003314 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3315 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08003316 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08003317
3318 // Add the windows to the dispatcher
3319 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
3320
3321 PointF pointInFirst = {300, 200};
3322 PointF pointInSecond = {300, 600};
3323
3324 // Send down to the first window
3325 NotifyMotionArgs firstDownMotionArgs =
3326 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3327 ADISPLAY_ID_DEFAULT, {pointInFirst});
3328 mDispatcher->notifyMotion(&firstDownMotionArgs);
3329 // Only the first window should get the down event
3330 firstWindow->consumeMotionDown();
3331 secondWindow->assertNoEvents();
3332
3333 // Send down to the second window
3334 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003335 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08003336 {pointInFirst, pointInSecond});
3337 mDispatcher->notifyMotion(&secondDownMotionArgs);
3338 // The first window gets a move and the second a down
3339 firstWindow->consumeMotionMove();
3340 secondWindow->consumeMotionDown();
3341
3342 // Send pointer cancel to the second window
3343 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003344 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08003345 {pointInFirst, pointInSecond});
3346 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
3347 mDispatcher->notifyMotion(&pointerUpMotionArgs);
3348 // The first window gets move and the second gets cancel.
3349 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
3350 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
3351
3352 // Send up event.
3353 NotifyMotionArgs upMotionArgs =
3354 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3355 ADISPLAY_ID_DEFAULT);
3356 mDispatcher->notifyMotion(&upMotionArgs);
3357 // The first window gets up and the second gets nothing.
3358 firstWindow->consumeMotionUp();
3359 secondWindow->assertNoEvents();
3360}
3361
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00003362TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
3363 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3364
3365 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003366 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00003367 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3368 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
3369 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
3370 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
3371
3372 window->sendTimeline(1 /*inputEventId*/, graphicsTimeline);
3373 window->assertNoEvents();
3374 mDispatcher->waitForIdle();
3375}
3376
chaviwd1c23182019-12-20 18:44:56 -08003377class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00003378public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07003379 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003380 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07003381 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08003382 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07003383 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00003384 }
3385
chaviwd1c23182019-12-20 18:44:56 -08003386 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
3387
3388 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
3389 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
3390 expectedDisplayId, expectedFlags);
3391 }
3392
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003393 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
3394
3395 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
3396
chaviwd1c23182019-12-20 18:44:56 -08003397 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
3398 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
3399 expectedDisplayId, expectedFlags);
3400 }
3401
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003402 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
3403 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE,
3404 expectedDisplayId, expectedFlags);
3405 }
3406
chaviwd1c23182019-12-20 18:44:56 -08003407 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
3408 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
3409 expectedDisplayId, expectedFlags);
3410 }
3411
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003412 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
3413 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
3414 expectedDisplayId, expectedFlags);
3415 }
3416
Arthur Hungfbfa5722021-11-16 02:45:54 +00003417 void consumeMotionPointerDown(int32_t pointerIdx) {
3418 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
3419 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3420 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, ADISPLAY_ID_DEFAULT,
3421 0 /*expectedFlags*/);
3422 }
3423
Evan Rosky84f07f02021-04-16 10:42:42 -07003424 MotionEvent* consumeMotion() {
3425 InputEvent* event = mInputReceiver->consume();
3426 if (!event) {
3427 ADD_FAILURE() << "No event was produced";
3428 return nullptr;
3429 }
3430 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
3431 ADD_FAILURE() << "Received event of type " << event->getType() << " instead of motion";
3432 return nullptr;
3433 }
3434 return static_cast<MotionEvent*>(event);
3435 }
3436
chaviwd1c23182019-12-20 18:44:56 -08003437 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
3438
3439private:
3440 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00003441};
3442
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003443using InputDispatcherMonitorTest = InputDispatcherTest;
3444
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003445/**
3446 * Two entities that receive touch: A window, and a global monitor.
3447 * The touch goes to the window, and then the window disappears.
3448 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
3449 * for the monitor, as well.
3450 * 1. foregroundWindow
3451 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
3452 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003453TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003454 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3455 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003456 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003457
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003458 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003459
3460 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3461 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3462 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3463 {100, 200}))
3464 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3465
3466 // Both the foreground window and the global monitor should receive the touch down
3467 window->consumeMotionDown();
3468 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3469
3470 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3471 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3472 ADISPLAY_ID_DEFAULT, {110, 200}))
3473 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3474
3475 window->consumeMotionMove();
3476 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
3477
3478 // Now the foreground window goes away
3479 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3480 window->consumeMotionCancel();
3481 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
3482
3483 // If more events come in, there will be no more foreground window to send them to. This will
3484 // cause a cancel for the monitor, as well.
3485 ASSERT_EQ(InputEventInjectionResult::FAILED,
3486 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3487 ADISPLAY_ID_DEFAULT, {120, 200}))
3488 << "Injection should fail because the window was removed";
3489 window->assertNoEvents();
3490 // Global monitor now gets the cancel
3491 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
3492}
3493
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003494TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07003495 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003496 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3497 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003498 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00003499
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003500 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00003501
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003502 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00003503 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003504 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00003505 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08003506 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00003507}
3508
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003509TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
3510 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00003511
Chris Yea209fde2020-07-22 13:54:51 -07003512 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003513 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3514 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003515 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00003516
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003517 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00003518 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003519 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08003520 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003521 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00003522
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003523 // Pilfer pointers from the monitor.
3524 // This should not do anything and the window should continue to receive events.
3525 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00003526
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003527 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003528 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3529 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003530 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003531
3532 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
3533 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00003534}
3535
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003536TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07003537 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003538 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3539 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07003540 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3541 window->setWindowOffset(20, 40);
3542 window->setWindowTransform(0, 1, -1, 0);
3543
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003544 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07003545
3546 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3547 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3548 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3549 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3550 MotionEvent* event = monitor.consumeMotion();
3551 // Even though window has transform, gesture monitor must not.
3552 ASSERT_EQ(ui::Transform(), event->getTransform());
3553}
3554
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003555TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00003556 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003557 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00003558
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003559 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00003560 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003561 << "Injection should fail if there is a monitor, but no touchable window";
3562 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00003563}
3564
chaviw81e2bb92019-12-18 15:03:51 -08003565TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003566 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003567 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3568 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08003569
Arthur Hung72d8dc32020-03-28 00:48:39 +00003570 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08003571
3572 NotifyMotionArgs motionArgs =
3573 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3574 ADISPLAY_ID_DEFAULT);
3575
3576 mDispatcher->notifyMotion(&motionArgs);
3577 // Window should receive motion down event.
3578 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3579
3580 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08003581 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08003582 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3583 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
3584 motionArgs.pointerCoords[0].getX() - 10);
3585
3586 mDispatcher->notifyMotion(&motionArgs);
3587 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
3588 0 /*expectedFlags*/);
3589}
3590
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003591/**
3592 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
3593 * the device default right away. In the test scenario, we check both the default value,
3594 * and the action of enabling / disabling.
3595 */
3596TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07003597 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003598 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3599 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08003600 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003601
3602 // Set focused application.
3603 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07003604 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003605
3606 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00003607 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003608 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003609 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
3610
3611 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07003612 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003613 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003614 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
3615
3616 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08003617 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Antonio Kanteka042c022022-07-06 16:51:07 -07003618 true /*hasPermission*/, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00003619 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07003620 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003621 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003622 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003623 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
3624
3625 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07003626 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003627 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003628 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
3629
3630 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08003631 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Antonio Kanteka042c022022-07-06 16:51:07 -07003632 true /*hasPermission*/, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00003633 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07003634 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003635 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003636 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003637 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
3638
3639 window->assertNoEvents();
3640}
3641
Gang Wange9087892020-01-07 12:17:14 -05003642TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003643 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003644 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3645 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05003646
3647 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07003648 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05003649
Arthur Hung72d8dc32020-03-28 00:48:39 +00003650 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003651 setFocusedWindow(window);
3652
Gang Wange9087892020-01-07 12:17:14 -05003653 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
3654
3655 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
3656 mDispatcher->notifyKey(&keyArgs);
3657
3658 InputEvent* event = window->consume();
3659 ASSERT_NE(event, nullptr);
3660
3661 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
3662 ASSERT_NE(verified, nullptr);
3663 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
3664
3665 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
3666 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
3667 ASSERT_EQ(keyArgs.source, verified->source);
3668 ASSERT_EQ(keyArgs.displayId, verified->displayId);
3669
3670 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
3671
3672 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05003673 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08003674 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05003675 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
3676 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
3677 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
3678 ASSERT_EQ(0, verifiedKey.repeatCount);
3679}
3680
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003681TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003682 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003683 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3684 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003685
3686 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3687
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07003688 ui::Transform transform;
3689 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
3690
3691 gui::DisplayInfo displayInfo;
3692 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
3693 displayInfo.transform = transform;
3694
3695 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003696
3697 NotifyMotionArgs motionArgs =
3698 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3699 ADISPLAY_ID_DEFAULT);
3700 mDispatcher->notifyMotion(&motionArgs);
3701
3702 InputEvent* event = window->consume();
3703 ASSERT_NE(event, nullptr);
3704
3705 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
3706 ASSERT_NE(verified, nullptr);
3707 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
3708
3709 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
3710 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
3711 EXPECT_EQ(motionArgs.source, verified->source);
3712 EXPECT_EQ(motionArgs.displayId, verified->displayId);
3713
3714 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
3715
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07003716 const vec2 rawXY =
3717 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
3718 motionArgs.pointerCoords[0].getXYValue());
3719 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
3720 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003721 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003722 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08003723 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003724 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
3725 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
3726}
3727
chaviw09c8d2d2020-08-24 15:48:26 -07003728/**
3729 * Ensure that separate calls to sign the same data are generating the same key.
3730 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
3731 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
3732 * tests.
3733 */
3734TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
3735 KeyEvent event = getTestKeyEvent();
3736 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
3737
3738 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
3739 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
3740 ASSERT_EQ(hmac1, hmac2);
3741}
3742
3743/**
3744 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
3745 */
3746TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
3747 KeyEvent event = getTestKeyEvent();
3748 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
3749 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
3750
3751 verifiedEvent.deviceId += 1;
3752 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3753
3754 verifiedEvent.source += 1;
3755 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3756
3757 verifiedEvent.eventTimeNanos += 1;
3758 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3759
3760 verifiedEvent.displayId += 1;
3761 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3762
3763 verifiedEvent.action += 1;
3764 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3765
3766 verifiedEvent.downTimeNanos += 1;
3767 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3768
3769 verifiedEvent.flags += 1;
3770 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3771
3772 verifiedEvent.keyCode += 1;
3773 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3774
3775 verifiedEvent.scanCode += 1;
3776 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3777
3778 verifiedEvent.metaState += 1;
3779 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3780
3781 verifiedEvent.repeatCount += 1;
3782 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3783}
3784
Vishnu Nair958da932020-08-21 17:12:37 -07003785TEST_F(InputDispatcherTest, SetFocusedWindow) {
3786 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3787 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003788 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003789 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003790 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003791 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3792
3793 // Top window is also focusable but is not granted focus.
3794 windowTop->setFocusable(true);
3795 windowSecond->setFocusable(true);
3796 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3797 setFocusedWindow(windowSecond);
3798
3799 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3801 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003802
3803 // Focused window should receive event.
3804 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
3805 windowTop->assertNoEvents();
3806}
3807
3808TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
3809 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3810 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003811 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003812 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3813
3814 window->setFocusable(true);
3815 // Release channel for window is no longer valid.
3816 window->releaseChannel();
3817 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3818 setFocusedWindow(window);
3819
3820 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003821 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3822 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003823
3824 // window channel is invalid, so it should not receive any input event.
3825 window->assertNoEvents();
3826}
3827
3828TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
3829 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3830 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003831 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08003832 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07003833 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3834
Vishnu Nair958da932020-08-21 17:12:37 -07003835 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3836 setFocusedWindow(window);
3837
3838 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003839 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3840 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003841
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08003842 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07003843 window->assertNoEvents();
3844}
3845
3846TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
3847 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3848 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003849 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003850 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003851 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003852 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3853
3854 windowTop->setFocusable(true);
3855 windowSecond->setFocusable(true);
3856 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3857 setFocusedWindow(windowTop);
3858 windowTop->consumeFocusEvent(true);
3859
3860 setFocusedWindow(windowSecond, windowTop);
3861 windowSecond->consumeFocusEvent(true);
3862 windowTop->consumeFocusEvent(false);
3863
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3865 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003866
3867 // Focused window should receive event.
3868 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
3869}
3870
3871TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
3872 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3873 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003874 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003875 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003876 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003877 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3878
3879 windowTop->setFocusable(true);
3880 windowSecond->setFocusable(true);
3881 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3882 setFocusedWindow(windowSecond, windowTop);
3883
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003884 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3885 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003886
3887 // Event should be dropped.
3888 windowTop->assertNoEvents();
3889 windowSecond->assertNoEvents();
3890}
3891
3892TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
3893 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3894 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003895 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003896 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003897 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
3898 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003899 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3900
3901 window->setFocusable(true);
3902 previousFocusedWindow->setFocusable(true);
3903 window->setVisible(false);
3904 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
3905 setFocusedWindow(previousFocusedWindow);
3906 previousFocusedWindow->consumeFocusEvent(true);
3907
3908 // Requesting focus on invisible window takes focus from currently focused window.
3909 setFocusedWindow(window);
3910 previousFocusedWindow->consumeFocusEvent(false);
3911
3912 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07003914 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003915 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07003916
3917 // Window does not get focus event or key down.
3918 window->assertNoEvents();
3919
3920 // Window becomes visible.
3921 window->setVisible(true);
3922 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3923
3924 // Window receives focus event.
3925 window->consumeFocusEvent(true);
3926 // Focused window receives key down.
3927 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3928}
3929
Vishnu Nair599f1412021-06-21 10:39:58 -07003930TEST_F(InputDispatcherTest, DisplayRemoved) {
3931 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3932 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003933 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07003934 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3935
3936 // window is granted focus.
3937 window->setFocusable(true);
3938 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3939 setFocusedWindow(window);
3940 window->consumeFocusEvent(true);
3941
3942 // When a display is removed window loses focus.
3943 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
3944 window->consumeFocusEvent(false);
3945}
3946
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003947/**
3948 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
3949 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
3950 * of the 'slipperyEnterWindow'.
3951 *
3952 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
3953 * a way so that the touched location is no longer covered by the top window.
3954 *
3955 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
3956 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
3957 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
3958 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
3959 * with ACTION_DOWN).
3960 * Thus, the touch has been transferred from the top window into the bottom window, because the top
3961 * window moved itself away from the touched location and had Flag::SLIPPERY.
3962 *
3963 * Even though the top window moved away from the touched location, it is still obscuring the bottom
3964 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
3965 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
3966 *
3967 * In this test, we ensure that the event received by the bottom window has
3968 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
3969 */
3970TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00003971 constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
3972 constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003973
3974 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3975 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3976
3977 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003978 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08003979 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003980 // Make sure this one overlaps the bottom window
3981 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
3982 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
3983 // one. Windows with the same owner are not considered to be occluding each other.
3984 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
3985
3986 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003987 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003988 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
3989
3990 mDispatcher->setInputWindows(
3991 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
3992
3993 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
3994 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3995 ADISPLAY_ID_DEFAULT, {{50, 50}});
3996 mDispatcher->notifyMotion(&args);
3997 slipperyExitWindow->consumeMotionDown();
3998 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
3999 mDispatcher->setInputWindows(
4000 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
4001
4002 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4003 ADISPLAY_ID_DEFAULT, {{51, 51}});
4004 mDispatcher->notifyMotion(&args);
4005
4006 slipperyExitWindow->consumeMotionCancel();
4007
4008 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
4009 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
4010}
4011
Garfield Tan1c7bc862020-01-28 13:24:04 -08004012class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
4013protected:
4014 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
4015 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
4016
Chris Yea209fde2020-07-22 13:54:51 -07004017 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08004018 sp<FakeWindowHandle> mWindow;
4019
4020 virtual void SetUp() override {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004021 mFakePolicy = sp<FakeInputDispatcherPolicy>::make();
Garfield Tan1c7bc862020-01-28 13:24:04 -08004022 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004023 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004024 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
4025 ASSERT_EQ(OK, mDispatcher->start());
4026
4027 setUpWindow();
4028 }
4029
4030 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07004031 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004032 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004033
Vishnu Nair47074b82020-08-14 11:54:47 -07004034 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004035 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004036 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004037 mWindow->consumeFocusEvent(true);
4038 }
4039
Chris Ye2ad95392020-09-01 13:44:44 -07004040 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08004041 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07004042 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08004043 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
4044 mDispatcher->notifyKey(&keyArgs);
4045
4046 // Window should receive key down event.
4047 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4048 }
4049
4050 void expectKeyRepeatOnce(int32_t repeatCount) {
4051 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
4052 InputEvent* repeatEvent = mWindow->consume();
4053 ASSERT_NE(nullptr, repeatEvent);
4054
4055 uint32_t eventType = repeatEvent->getType();
4056 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
4057
4058 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
4059 uint32_t eventAction = repeatKeyEvent->getAction();
4060 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
4061 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
4062 }
4063
Chris Ye2ad95392020-09-01 13:44:44 -07004064 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08004065 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07004066 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08004067 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
4068 mDispatcher->notifyKey(&keyArgs);
4069
4070 // Window should receive key down event.
4071 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
4072 0 /*expectedFlags*/);
4073 }
4074};
4075
4076TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Chris Ye2ad95392020-09-01 13:44:44 -07004077 sendAndConsumeKeyDown(1 /* deviceId */);
4078 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
4079 expectKeyRepeatOnce(repeatCount);
4080 }
4081}
4082
4083TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
4084 sendAndConsumeKeyDown(1 /* deviceId */);
4085 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
4086 expectKeyRepeatOnce(repeatCount);
4087 }
4088 sendAndConsumeKeyDown(2 /* deviceId */);
4089 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08004090 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
4091 expectKeyRepeatOnce(repeatCount);
4092 }
4093}
4094
4095TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Chris Ye2ad95392020-09-01 13:44:44 -07004096 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004097 expectKeyRepeatOnce(1 /*repeatCount*/);
Chris Ye2ad95392020-09-01 13:44:44 -07004098 sendAndConsumeKeyUp(1 /* deviceId */);
4099 mWindow->assertNoEvents();
4100}
4101
4102TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
4103 sendAndConsumeKeyDown(1 /* deviceId */);
4104 expectKeyRepeatOnce(1 /*repeatCount*/);
4105 sendAndConsumeKeyDown(2 /* deviceId */);
4106 expectKeyRepeatOnce(1 /*repeatCount*/);
4107 // Stale key up from device 1.
4108 sendAndConsumeKeyUp(1 /* deviceId */);
4109 // Device 2 is still down, keep repeating
4110 expectKeyRepeatOnce(2 /*repeatCount*/);
4111 expectKeyRepeatOnce(3 /*repeatCount*/);
4112 // Device 2 key up
4113 sendAndConsumeKeyUp(2 /* deviceId */);
4114 mWindow->assertNoEvents();
4115}
4116
4117TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
4118 sendAndConsumeKeyDown(1 /* deviceId */);
4119 expectKeyRepeatOnce(1 /*repeatCount*/);
4120 sendAndConsumeKeyDown(2 /* deviceId */);
4121 expectKeyRepeatOnce(1 /*repeatCount*/);
4122 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
4123 sendAndConsumeKeyUp(2 /* deviceId */);
4124 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08004125 mWindow->assertNoEvents();
4126}
4127
liushenxiang42232912021-05-21 20:24:09 +08004128TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
4129 sendAndConsumeKeyDown(DEVICE_ID);
4130 expectKeyRepeatOnce(1 /*repeatCount*/);
4131 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
4132 mDispatcher->notifyDeviceReset(&args);
4133 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
4134 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
4135 mWindow->assertNoEvents();
4136}
4137
Garfield Tan1c7bc862020-01-28 13:24:04 -08004138TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Chris Ye2ad95392020-09-01 13:44:44 -07004139 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004140 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
4141 InputEvent* repeatEvent = mWindow->consume();
4142 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
4143 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
4144 IdGenerator::getSource(repeatEvent->getId()));
4145 }
4146}
4147
4148TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Chris Ye2ad95392020-09-01 13:44:44 -07004149 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004150
4151 std::unordered_set<int32_t> idSet;
4152 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
4153 InputEvent* repeatEvent = mWindow->consume();
4154 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
4155 int32_t id = repeatEvent->getId();
4156 EXPECT_EQ(idSet.end(), idSet.find(id));
4157 idSet.insert(id);
4158 }
4159}
4160
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004161/* Test InputDispatcher for MultiDisplay */
4162class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
4163public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07004164 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004165 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08004166
Chris Yea209fde2020-07-22 13:54:51 -07004167 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004168 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004169 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004170
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004171 // Set focus window for primary display, but focused display would be second one.
4172 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07004173 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004174 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004175 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004176 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08004177
Chris Yea209fde2020-07-22 13:54:51 -07004178 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004179 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004180 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004181 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004182 // Set focus display to second one.
4183 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
4184 // Set focus window for second display.
4185 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07004186 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004187 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004188 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004189 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004190 }
4191
Prabir Pradhan3608aad2019-10-02 17:08:26 -07004192 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004193 InputDispatcherTest::TearDown();
4194
Chris Yea209fde2020-07-22 13:54:51 -07004195 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004196 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07004197 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004198 windowInSecondary.clear();
4199 }
4200
4201protected:
Chris Yea209fde2020-07-22 13:54:51 -07004202 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004203 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07004204 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004205 sp<FakeWindowHandle> windowInSecondary;
4206};
4207
4208TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
4209 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4211 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
4212 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004213 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08004214 windowInSecondary->assertNoEvents();
4215
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004216 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4218 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
4219 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08004220 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004221 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08004222}
4223
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004224TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08004225 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004226 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4227 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004228 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004229 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08004230 windowInSecondary->assertNoEvents();
4231
4232 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004233 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004234 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08004235 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004236 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08004237
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004238 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00004239 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08004240
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004241 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004242 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
4243 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08004244
4245 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004246 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004247 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08004248 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004249 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08004250 windowInSecondary->assertNoEvents();
4251}
4252
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004253// Test per-display input monitors for motion event.
4254TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08004255 FakeMonitorReceiver monitorInPrimary =
4256 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
4257 FakeMonitorReceiver monitorInSecondary =
4258 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004259
4260 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004261 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4262 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
4263 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004264 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08004265 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004266 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08004267 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004268
4269 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4271 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
4272 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004273 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08004274 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004275 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08004276 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004277
4278 // Test inject a non-pointer motion event.
4279 // If specific a display, it will dispatch to the focused window of particular display,
4280 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4282 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
4283 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004284 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08004285 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004286 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08004287 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004288}
4289
4290// Test per-display input monitors for key event.
4291TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004292 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08004293 FakeMonitorReceiver monitorInPrimary =
4294 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
4295 FakeMonitorReceiver monitorInSecondary =
4296 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004297
4298 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4300 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004301 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08004302 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004303 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08004304 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004305}
4306
Vishnu Nair958da932020-08-21 17:12:37 -07004307TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
4308 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004309 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07004310 secondWindowInPrimary->setFocusable(true);
4311 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
4312 setFocusedWindow(secondWindowInPrimary);
4313 windowInPrimary->consumeFocusEvent(false);
4314 secondWindowInPrimary->consumeFocusEvent(true);
4315
4316 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
4318 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004319 windowInPrimary->assertNoEvents();
4320 windowInSecondary->assertNoEvents();
4321 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4322}
4323
Arthur Hungdfd528e2021-12-08 13:23:04 +00004324TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
4325 FakeMonitorReceiver monitorInPrimary =
4326 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
4327 FakeMonitorReceiver monitorInSecondary =
4328 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
4329
4330 // Test touch down on primary display.
4331 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4332 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
4333 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4334 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4335 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4336
4337 // Test touch down on second display.
4338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4339 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
4340 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4341 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
4342 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
4343
4344 // Trigger cancel touch.
4345 mDispatcher->cancelCurrentTouch();
4346 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
4347 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
4348 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
4349 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
4350
4351 // Test inject a move motion event, no window/monitor should receive the event.
4352 ASSERT_EQ(InputEventInjectionResult::FAILED,
4353 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4354 ADISPLAY_ID_DEFAULT, {110, 200}))
4355 << "Inject motion event should return InputEventInjectionResult::FAILED";
4356 windowInPrimary->assertNoEvents();
4357 monitorInPrimary.assertNoEvents();
4358
4359 ASSERT_EQ(InputEventInjectionResult::FAILED,
4360 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4361 SECOND_DISPLAY_ID, {110, 200}))
4362 << "Inject motion event should return InputEventInjectionResult::FAILED";
4363 windowInSecondary->assertNoEvents();
4364 monitorInSecondary.assertNoEvents();
4365}
4366
Jackal Guof9696682018-10-05 12:23:23 +08004367class InputFilterTest : public InputDispatcherTest {
4368protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07004369 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
4370 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08004371 NotifyMotionArgs motionArgs;
4372
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004373 motionArgs =
4374 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08004375 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004376 motionArgs =
4377 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08004378 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004379 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08004380 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07004381 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
4382 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08004383 } else {
4384 mFakePolicy->assertFilterInputEventWasNotCalled();
4385 }
4386 }
4387
4388 void testNotifyKey(bool expectToBeFiltered) {
4389 NotifyKeyArgs keyArgs;
4390
4391 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
4392 mDispatcher->notifyKey(&keyArgs);
4393 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
4394 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004395 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08004396
4397 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08004398 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08004399 } else {
4400 mFakePolicy->assertFilterInputEventWasNotCalled();
4401 }
4402 }
4403};
4404
4405// Test InputFilter for MotionEvent
4406TEST_F(InputFilterTest, MotionEvent_InputFilter) {
4407 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
4408 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
4409 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
4410
4411 // Enable InputFilter
4412 mDispatcher->setInputFilterEnabled(true);
4413 // Test touch on both primary and second display, and check if both events are filtered.
4414 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
4415 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
4416
4417 // Disable InputFilter
4418 mDispatcher->setInputFilterEnabled(false);
4419 // Test touch on both primary and second display, and check if both events aren't filtered.
4420 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
4421 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
4422}
4423
4424// Test InputFilter for KeyEvent
4425TEST_F(InputFilterTest, KeyEvent_InputFilter) {
4426 // Since the InputFilter is disabled by default, check if key event aren't filtered.
4427 testNotifyKey(/*expectToBeFiltered*/ false);
4428
4429 // Enable InputFilter
4430 mDispatcher->setInputFilterEnabled(true);
4431 // Send a key event, and check if it is filtered.
4432 testNotifyKey(/*expectToBeFiltered*/ true);
4433
4434 // Disable InputFilter
4435 mDispatcher->setInputFilterEnabled(false);
4436 // Send a key event, and check if it isn't filtered.
4437 testNotifyKey(/*expectToBeFiltered*/ false);
4438}
4439
Prabir Pradhan81420cc2021-09-06 10:28:50 -07004440// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
4441// logical display coordinate space.
4442TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
4443 ui::Transform firstDisplayTransform;
4444 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
4445 ui::Transform secondDisplayTransform;
4446 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
4447
4448 std::vector<gui::DisplayInfo> displayInfos(2);
4449 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
4450 displayInfos[0].transform = firstDisplayTransform;
4451 displayInfos[1].displayId = SECOND_DISPLAY_ID;
4452 displayInfos[1].transform = secondDisplayTransform;
4453
4454 mDispatcher->onWindowInfosChanged({}, displayInfos);
4455
4456 // Enable InputFilter
4457 mDispatcher->setInputFilterEnabled(true);
4458
4459 // Ensure the correct transforms are used for the displays.
4460 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
4461 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
4462}
4463
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004464class InputFilterInjectionPolicyTest : public InputDispatcherTest {
4465protected:
4466 virtual void SetUp() override {
4467 InputDispatcherTest::SetUp();
4468
4469 /**
4470 * We don't need to enable input filter to test the injected event policy, but we enabled it
4471 * here to make the tests more realistic, since this policy only matters when inputfilter is
4472 * on.
4473 */
4474 mDispatcher->setInputFilterEnabled(true);
4475
4476 std::shared_ptr<InputApplicationHandle> application =
4477 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004478 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
4479 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004480
4481 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4482 mWindow->setFocusable(true);
4483 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4484 setFocusedWindow(mWindow);
4485 mWindow->consumeFocusEvent(true);
4486 }
4487
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004488 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
4489 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004490 KeyEvent event;
4491
4492 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
4493 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
4494 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
4495 KEY_A, AMETA_NONE, 0 /*repeatCount*/, eventTime, eventTime);
4496 const int32_t additionalPolicyFlags =
4497 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
4498 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan5735a322022-04-11 17:23:34 +00004499 mDispatcher->injectInputEvent(&event, {} /*targetUid*/,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004500 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
4501 policyFlags | additionalPolicyFlags));
4502
4503 InputEvent* received = mWindow->consume();
4504 ASSERT_NE(nullptr, received);
4505 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004506 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_KEY);
4507 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
4508 ASSERT_EQ(flags, keyEvent.getFlags());
4509 }
4510
4511 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
4512 int32_t flags) {
4513 MotionEvent event;
4514 PointerProperties pointerProperties[1];
4515 PointerCoords pointerCoords[1];
4516 pointerProperties[0].clear();
4517 pointerProperties[0].id = 0;
4518 pointerCoords[0].clear();
4519 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
4520 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
4521
4522 ui::Transform identityTransform;
4523 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
4524 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
4525 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
4526 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
4527 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07004528 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07004529 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004530 /*pointerCount*/ 1, pointerProperties, pointerCoords);
4531
4532 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
4533 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan5735a322022-04-11 17:23:34 +00004534 mDispatcher->injectInputEvent(&event, {} /*targetUid*/,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004535 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
4536 policyFlags | additionalPolicyFlags));
4537
4538 InputEvent* received = mWindow->consume();
4539 ASSERT_NE(nullptr, received);
4540 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
4541 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_MOTION);
4542 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
4543 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004544 }
4545
4546private:
4547 sp<FakeWindowHandle> mWindow;
4548};
4549
4550TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004551 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
4552 // filter. Without it, the event will no different from a regularly injected event, and the
4553 // injected device id will be overwritten.
4554 testInjectedKey(POLICY_FLAG_FILTERED, 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
4555 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004556}
4557
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004558TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004559 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004560 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
4561 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4562}
4563
4564TEST_F(InputFilterInjectionPolicyTest,
4565 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
4566 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
4567 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
4568 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004569}
4570
4571TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
4572 testInjectedKey(0 /*policyFlags*/, 3 /*injectedDeviceId*/,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004573 VIRTUAL_KEYBOARD_ID /*resolvedDeviceId*/, 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004574}
4575
chaviwfd6d3512019-03-25 13:23:49 -07004576class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07004577 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07004578 InputDispatcherTest::SetUp();
4579
Chris Yea209fde2020-07-22 13:54:51 -07004580 std::shared_ptr<FakeApplicationHandle> application =
4581 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004582 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004583 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07004584 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07004585
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004586 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004587 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004588 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07004589
4590 // Set focused application.
4591 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07004592 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07004593
4594 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00004595 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004596 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004597 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07004598 }
4599
Prabir Pradhan3608aad2019-10-02 17:08:26 -07004600 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07004601 InputDispatcherTest::TearDown();
4602
4603 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004604 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07004605 }
4606
4607protected:
4608 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004609 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004610 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07004611};
4612
4613// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
4614// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
4615// the onPointerDownOutsideFocus callback.
4616TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004618 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4619 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004620 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004621 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07004622
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004623 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07004624 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
4625}
4626
4627// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
4628// DOWN on the window that doesn't have focus. Ensure no window received the
4629// onPointerDownOutsideFocus callback.
4630TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004632 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004633 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004634 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07004635
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004636 ASSERT_TRUE(mDispatcher->waitForIdle());
4637 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07004638}
4639
4640// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
4641// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
4642TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004643 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4644 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004645 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004646 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07004647
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004648 ASSERT_TRUE(mDispatcher->waitForIdle());
4649 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07004650}
4651
4652// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
4653// DOWN on the window that already has focus. Ensure no window received the
4654// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004655TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004657 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004658 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004659 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004660 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07004661
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004662 ASSERT_TRUE(mDispatcher->waitForIdle());
4663 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07004664}
4665
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08004666// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
4667// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
4668TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
4669 const MotionEvent event =
4670 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4671 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
4672 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(20).y(20))
4673 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
4674 .build();
4675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
4676 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4677 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
4678
4679 ASSERT_TRUE(mDispatcher->waitForIdle());
4680 mFakePolicy->assertOnPointerDownWasNotCalled();
4681 // Ensure that the unfocused window did not receive any FOCUS events.
4682 mUnfocusedWindow->assertNoEvents();
4683}
4684
chaviwaf87b3e2019-10-01 16:59:28 -07004685// These tests ensures we can send touch events to a single client when there are multiple input
4686// windows that point to the same client token.
4687class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
4688 virtual void SetUp() override {
4689 InputDispatcherTest::SetUp();
4690
Chris Yea209fde2020-07-22 13:54:51 -07004691 std::shared_ptr<FakeApplicationHandle> application =
4692 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004693 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
4694 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07004695 mWindow1->setFrame(Rect(0, 0, 100, 100));
4696
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004697 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
4698 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07004699 mWindow2->setFrame(Rect(100, 100, 200, 200));
4700
Arthur Hung72d8dc32020-03-28 00:48:39 +00004701 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07004702 }
4703
4704protected:
4705 sp<FakeWindowHandle> mWindow1;
4706 sp<FakeWindowHandle> mWindow2;
4707
4708 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05004709 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07004710 vec2 vals = windowInfo->transform.transform(point.x, point.y);
4711 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07004712 }
4713
4714 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
4715 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004716 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07004717 InputEvent* event = window->consume();
4718
4719 ASSERT_NE(nullptr, event) << name.c_str()
4720 << ": consumer should have returned non-NULL event.";
4721
4722 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
4723 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
4724 << " event, got " << inputEventTypeToString(event->getType()) << " event";
4725
4726 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004727 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08004728 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07004729
4730 for (size_t i = 0; i < points.size(); i++) {
4731 float expectedX = points[i].x;
4732 float expectedY = points[i].y;
4733
4734 EXPECT_EQ(expectedX, motionEvent.getX(i))
4735 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
4736 << ", got " << motionEvent.getX(i);
4737 EXPECT_EQ(expectedY, motionEvent.getY(i))
4738 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
4739 << ", got " << motionEvent.getY(i);
4740 }
4741 }
chaviw9eaa22c2020-07-01 16:21:27 -07004742
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08004743 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07004744 std::vector<PointF> expectedPoints) {
4745 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
4746 ADISPLAY_ID_DEFAULT, touchedPoints);
4747 mDispatcher->notifyMotion(&motionArgs);
4748
4749 // Always consume from window1 since it's the window that has the InputReceiver
4750 consumeMotionEvent(mWindow1, action, expectedPoints);
4751 }
chaviwaf87b3e2019-10-01 16:59:28 -07004752};
4753
4754TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
4755 // Touch Window 1
4756 PointF touchedPoint = {10, 10};
4757 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07004758 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004759
4760 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07004761 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004762
4763 // Touch Window 2
4764 touchedPoint = {150, 150};
4765 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07004766 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004767}
4768
chaviw9eaa22c2020-07-01 16:21:27 -07004769TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
4770 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07004771 mWindow2->setWindowScale(0.5f, 0.5f);
4772
4773 // Touch Window 1
4774 PointF touchedPoint = {10, 10};
4775 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07004776 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004777 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07004778 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004779
4780 // Touch Window 2
4781 touchedPoint = {150, 150};
4782 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07004783 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
4784 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004785
chaviw9eaa22c2020-07-01 16:21:27 -07004786 // Update the transform so rotation is set
4787 mWindow2->setWindowTransform(0, -1, 1, 0);
4788 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
4789 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004790}
4791
chaviw9eaa22c2020-07-01 16:21:27 -07004792TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004793 mWindow2->setWindowScale(0.5f, 0.5f);
4794
4795 // Touch Window 1
4796 std::vector<PointF> touchedPoints = {PointF{10, 10}};
4797 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07004798 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004799
4800 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07004801 touchedPoints.push_back(PointF{150, 150});
4802 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004803 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004804
chaviw9eaa22c2020-07-01 16:21:27 -07004805 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004806 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07004807 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004808
chaviw9eaa22c2020-07-01 16:21:27 -07004809 // Update the transform so rotation is set for Window 2
4810 mWindow2->setWindowTransform(0, -1, 1, 0);
4811 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004812 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004813}
4814
chaviw9eaa22c2020-07-01 16:21:27 -07004815TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004816 mWindow2->setWindowScale(0.5f, 0.5f);
4817
4818 // Touch Window 1
4819 std::vector<PointF> touchedPoints = {PointF{10, 10}};
4820 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07004821 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004822
4823 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07004824 touchedPoints.push_back(PointF{150, 150});
4825 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004826
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004827 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004828
4829 // Move both windows
4830 touchedPoints = {{20, 20}, {175, 175}};
4831 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
4832 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
4833
chaviw9eaa22c2020-07-01 16:21:27 -07004834 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004835
chaviw9eaa22c2020-07-01 16:21:27 -07004836 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004837 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07004838 expectedPoints.pop_back();
4839
4840 // Touch Window 2
4841 mWindow2->setWindowTransform(0, -1, 1, 0);
4842 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004843 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07004844
4845 // Move both windows
4846 touchedPoints = {{20, 20}, {175, 175}};
4847 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
4848 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
4849
4850 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004851}
4852
4853TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
4854 mWindow1->setWindowScale(0.5f, 0.5f);
4855
4856 // Touch Window 1
4857 std::vector<PointF> touchedPoints = {PointF{10, 10}};
4858 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07004859 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004860
4861 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07004862 touchedPoints.push_back(PointF{150, 150});
4863 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004864
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004865 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004866
4867 // Move both windows
4868 touchedPoints = {{20, 20}, {175, 175}};
4869 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
4870 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
4871
chaviw9eaa22c2020-07-01 16:21:27 -07004872 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004873}
4874
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004875class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
4876 virtual void SetUp() override {
4877 InputDispatcherTest::SetUp();
4878
Chris Yea209fde2020-07-22 13:54:51 -07004879 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004880 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004881 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
4882 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004883 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05004884 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07004885 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004886
4887 // Set focused application.
4888 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
4889
4890 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004891 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004892 mWindow->consumeFocusEvent(true);
4893 }
4894
4895 virtual void TearDown() override {
4896 InputDispatcherTest::TearDown();
4897 mWindow.clear();
4898 }
4899
4900protected:
Chris Yea209fde2020-07-22 13:54:51 -07004901 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004902 sp<FakeWindowHandle> mWindow;
4903 static constexpr PointF WINDOW_LOCATION = {20, 20};
4904
4905 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004907 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4908 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004909 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004910 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4911 WINDOW_LOCATION));
4912 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004913
4914 sp<FakeWindowHandle> addSpyWindow() {
4915 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004916 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004917 spy->setTrustedOverlay(true);
4918 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08004919 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004920 spy->setDispatchingTimeout(30ms);
4921 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
4922 return spy;
4923 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004924};
4925
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004926// Send a tap and respond, which should not cause an ANR.
4927TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
4928 tapOnWindow();
4929 mWindow->consumeMotionDown();
4930 mWindow->consumeMotionUp();
4931 ASSERT_TRUE(mDispatcher->waitForIdle());
4932 mFakePolicy->assertNotifyAnrWasNotCalled();
4933}
4934
4935// Send a regular key and respond, which should not cause an ANR.
4936TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004938 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
4939 ASSERT_TRUE(mDispatcher->waitForIdle());
4940 mFakePolicy->assertNotifyAnrWasNotCalled();
4941}
4942
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004943TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
4944 mWindow->setFocusable(false);
4945 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4946 mWindow->consumeFocusEvent(false);
4947
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004948 InputEventInjectionResult result =
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004949 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004950 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
4951 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004952 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004953 // Key will not go to window because we have no focused window.
4954 // The 'no focused window' ANR timer should start instead.
4955
4956 // Now, the focused application goes away.
4957 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
4958 // The key should get dropped and there should be no ANR.
4959
4960 ASSERT_TRUE(mDispatcher->waitForIdle());
4961 mFakePolicy->assertNotifyAnrWasNotCalled();
4962}
4963
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004964// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004965// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
4966// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004967TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004968 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004969 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4970 WINDOW_LOCATION));
4971
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004972 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
4973 ASSERT_TRUE(sequenceNum);
4974 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08004975 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004976
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004977 mWindow->finishEvent(*sequenceNum);
4978 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
4979 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004980 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08004981 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004982}
4983
4984// Send a key to the app and have the app not respond right away.
4985TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
4986 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004987 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004988 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
4989 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004990 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08004991 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004992 ASSERT_TRUE(mDispatcher->waitForIdle());
4993}
4994
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004995// We have a focused application, but no focused window
4996TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004997 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004998 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4999 mWindow->consumeFocusEvent(false);
5000
5001 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005002 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005003 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5004 WINDOW_LOCATION));
5005 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
5006 mDispatcher->waitForIdle();
5007 mFakePolicy->assertNotifyAnrWasNotCalled();
5008
5009 // Once a focused event arrives, we get an ANR for this application
5010 // We specify the injection timeout to be smaller than the application timeout, to ensure that
5011 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005012 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005013 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005014 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005015 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005016 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07005017 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005018 ASSERT_TRUE(mDispatcher->waitForIdle());
5019}
5020
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08005021/**
5022 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
5023 * there will not be an ANR.
5024 */
5025TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
5026 mWindow->setFocusable(false);
5027 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5028 mWindow->consumeFocusEvent(false);
5029
5030 KeyEvent event;
5031 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
5032 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
5033
5034 // Define a valid key down event that is stale (too old).
5035 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
5036 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
5037 AMETA_NONE, 1 /*repeatCount*/, eventTime, eventTime);
5038
5039 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
5040
5041 InputEventInjectionResult result =
Prabir Pradhan5735a322022-04-11 17:23:34 +00005042 mDispatcher->injectInputEvent(&event, {} /* targetUid */,
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08005043 InputEventInjectionSync::WAIT_FOR_RESULT,
5044 INJECT_EVENT_TIMEOUT, policyFlags);
5045 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
5046 << "Injection should fail because the event is stale";
5047
5048 ASSERT_TRUE(mDispatcher->waitForIdle());
5049 mFakePolicy->assertNotifyAnrWasNotCalled();
5050 mWindow->assertNoEvents();
5051}
5052
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005053// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005054// Make sure that we don't notify policy twice about the same ANR.
5055TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07005056 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005057 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5058 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005059
5060 // Once a focused event arrives, we get an ANR for this application
5061 // We specify the injection timeout to be smaller than the application timeout, to ensure that
5062 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005063 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005064 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005065 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005066 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07005067 const std::chrono::duration appTimeout =
5068 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
5069 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005070
Vishnu Naire4df8752022-09-08 09:17:55 -07005071 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005072 // ANR should not be raised again. It is up to policy to do that if it desires.
5073 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005074
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005075 // If we now get a focused window, the ANR should stop, but the policy handles that via
5076 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005077 ASSERT_TRUE(mDispatcher->waitForIdle());
5078}
5079
5080// We have a focused application, but no focused window
5081TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07005082 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005083 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5084 mWindow->consumeFocusEvent(false);
5085
5086 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005087 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005088 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005089 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
5090 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005091
Vishnu Naire4df8752022-09-08 09:17:55 -07005092 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
5093 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005094
5095 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005096 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005097 ASSERT_TRUE(mDispatcher->waitForIdle());
5098 mWindow->assertNoEvents();
5099}
5100
5101/**
5102 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
5103 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
5104 * If we process 1 of the events, but ANR on the second event with the same timestamp,
5105 * the ANR mechanism should still work.
5106 *
5107 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
5108 * DOWN event, while not responding on the second one.
5109 */
5110TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
5111 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
5112 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5113 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
5114 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
5115 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005116 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005117
5118 // Now send ACTION_UP, with identical timestamp
5119 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5120 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
5121 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
5122 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005123 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005124
5125 // We have now sent down and up. Let's consume first event and then ANR on the second.
5126 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5127 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005128 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005129}
5130
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005131// A spy window can receive an ANR
5132TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
5133 sp<FakeWindowHandle> spy = addSpyWindow();
5134
5135 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5136 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5137 WINDOW_LOCATION));
5138 mWindow->consumeMotionDown();
5139
5140 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
5141 ASSERT_TRUE(sequenceNum);
5142 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005143 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005144
5145 spy->finishEvent(*sequenceNum);
5146 spy->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
5147 0 /*flags*/);
5148 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08005149 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005150}
5151
5152// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005153// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005154TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
5155 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005156
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005157 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5158 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005159 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005160 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005161
5162 // Stuck on the ACTION_UP
5163 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005164 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005165
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005166 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005167 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005168 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5169 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005170
5171 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
5172 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005173 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005174 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005175 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005176}
5177
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005178// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005179// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005180TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
5181 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005182
5183 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005184 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5185 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005186
5187 mWindow->consumeMotionDown();
5188 // Stuck on the ACTION_UP
5189 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005190 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005191
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005192 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005193 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005194 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5195 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005196
5197 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
5198 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005199 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005200 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005201 spy->assertNoEvents();
5202}
5203
5204TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
5205 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
5206
5207 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5208
5209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5210 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5211 WINDOW_LOCATION));
5212
5213 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5214 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
5215 ASSERT_TRUE(consumeSeq);
5216
Prabir Pradhanedd96402022-02-15 01:46:16 -08005217 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005218
5219 monitor.finishEvent(*consumeSeq);
5220 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5221
5222 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08005223 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005224}
5225
5226// If a window is unresponsive, then you get anr. if the window later catches up and starts to
5227// process events, you don't get an anr. When the window later becomes unresponsive again, you
5228// get an ANR again.
5229// 1. tap -> block on ACTION_UP -> receive ANR
5230// 2. consume all pending events (= queue becomes healthy again)
5231// 3. tap again -> block on ACTION_UP again -> receive ANR second time
5232TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
5233 tapOnWindow();
5234
5235 mWindow->consumeMotionDown();
5236 // Block on ACTION_UP
5237 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005238 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005239 mWindow->consumeMotionUp(); // Now the connection should be healthy again
5240 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005241 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005242 mWindow->assertNoEvents();
5243
5244 tapOnWindow();
5245 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005246 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005247 mWindow->consumeMotionUp();
5248
5249 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005250 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005251 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005252 mWindow->assertNoEvents();
5253}
5254
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005255// If a connection remains unresponsive for a while, make sure policy is only notified once about
5256// it.
5257TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005259 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5260 WINDOW_LOCATION));
5261
5262 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005263 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005264 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005265 // 'notifyConnectionUnresponsive' should only be called once per connection
5266 mFakePolicy->assertNotifyAnrWasNotCalled();
5267 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005268 mWindow->consumeMotionDown();
5269 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
5270 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
5271 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005272 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005273 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005274 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005275}
5276
5277/**
5278 * If a window is processing a motion event, and then a key event comes in, the key event should
5279 * not to to the focused window until the motion is processed.
5280 *
5281 * Warning!!!
5282 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
5283 * and the injection timeout that we specify when injecting the key.
5284 * We must have the injection timeout (10ms) be smaller than
5285 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
5286 *
5287 * If that value changes, this test should also change.
5288 */
5289TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
5290 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
5291 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5292
5293 tapOnWindow();
5294 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
5295 ASSERT_TRUE(downSequenceNum);
5296 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
5297 ASSERT_TRUE(upSequenceNum);
5298 // Don't finish the events yet, and send a key
5299 // Injection will "succeed" because we will eventually give up and send the key to the focused
5300 // window even if motions are still being processed. But because the injection timeout is short,
5301 // we will receive INJECTION_TIMED_OUT as the result.
5302
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005303 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005304 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005305 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
5306 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005307 // Key will not be sent to the window, yet, because the window is still processing events
5308 // and the key remains pending, waiting for the touch events to be processed
5309 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
5310 ASSERT_FALSE(keySequenceNum);
5311
5312 std::this_thread::sleep_for(500ms);
5313 // if we wait long enough though, dispatcher will give up, and still send the key
5314 // to the focused window, even though we have not yet finished the motion event
5315 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5316 mWindow->finishEvent(*downSequenceNum);
5317 mWindow->finishEvent(*upSequenceNum);
5318}
5319
5320/**
5321 * If a window is processing a motion event, and then a key event comes in, the key event should
5322 * not go to the focused window until the motion is processed.
5323 * If then a new motion comes in, then the pending key event should be going to the currently
5324 * focused window right away.
5325 */
5326TEST_F(InputDispatcherSingleWindowAnr,
5327 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
5328 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
5329 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5330
5331 tapOnWindow();
5332 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
5333 ASSERT_TRUE(downSequenceNum);
5334 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
5335 ASSERT_TRUE(upSequenceNum);
5336 // Don't finish the events yet, and send a key
5337 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005339 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005340 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005341 // At this point, key is still pending, and should not be sent to the application yet.
5342 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
5343 ASSERT_FALSE(keySequenceNum);
5344
5345 // Now tap down again. It should cause the pending key to go to the focused window right away.
5346 tapOnWindow();
5347 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
5348 // the other events yet. We can finish events in any order.
5349 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
5350 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
5351 mWindow->consumeMotionDown();
5352 mWindow->consumeMotionUp();
5353 mWindow->assertNoEvents();
5354}
5355
5356class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
5357 virtual void SetUp() override {
5358 InputDispatcherTest::SetUp();
5359
Chris Yea209fde2020-07-22 13:54:51 -07005360 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005361 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005362 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
5363 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005364 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005365 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005366 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005367
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005368 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
5369 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05005370 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005371 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005372
5373 // Set focused application.
5374 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07005375 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005376
5377 // Expect one focus window exist in display.
5378 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005379 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005380 mFocusedWindow->consumeFocusEvent(true);
5381 }
5382
5383 virtual void TearDown() override {
5384 InputDispatcherTest::TearDown();
5385
5386 mUnfocusedWindow.clear();
5387 mFocusedWindow.clear();
5388 }
5389
5390protected:
Chris Yea209fde2020-07-22 13:54:51 -07005391 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005392 sp<FakeWindowHandle> mUnfocusedWindow;
5393 sp<FakeWindowHandle> mFocusedWindow;
5394 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
5395 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
5396 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
5397
5398 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
5399
5400 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
5401
5402private:
5403 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005404 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005405 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5406 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005407 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005408 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5409 location));
5410 }
5411};
5412
5413// If we have 2 windows that are both unresponsive, the one with the shortest timeout
5414// should be ANR'd first.
5415TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005416 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005417 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5418 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005419 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005420 mFocusedWindow->consumeMotionDown();
5421 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
5422 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
5423 // We consumed all events, so no ANR
5424 ASSERT_TRUE(mDispatcher->waitForIdle());
5425 mFakePolicy->assertNotifyAnrWasNotCalled();
5426
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005428 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5429 FOCUSED_WINDOW_LOCATION));
5430 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
5431 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005432
5433 const std::chrono::duration timeout =
5434 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005435 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005436 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
5437 // sequence to make it consistent
5438 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005439 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005440 mFocusedWindow->consumeMotionDown();
5441 // This cancel is generated because the connection was unresponsive
5442 mFocusedWindow->consumeMotionCancel();
5443 mFocusedWindow->assertNoEvents();
5444 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005445 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08005446 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
5447 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005448 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005449}
5450
5451// If we have 2 windows with identical timeouts that are both unresponsive,
5452// it doesn't matter which order they should have ANR.
5453// But we should receive ANR for both.
5454TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
5455 // Set the timeout for unfocused window to match the focused window
5456 mUnfocusedWindow->setDispatchingTimeout(10ms);
5457 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
5458
5459 tapOnFocusedWindow();
5460 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08005461 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
5462 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
5463 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005464
5465 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005466 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
5467 mFocusedWindow->getToken() == anrConnectionToken2);
5468 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
5469 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005470
5471 ASSERT_TRUE(mDispatcher->waitForIdle());
5472 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005473
5474 mFocusedWindow->consumeMotionDown();
5475 mFocusedWindow->consumeMotionUp();
5476 mUnfocusedWindow->consumeMotionOutside();
5477
Prabir Pradhanedd96402022-02-15 01:46:16 -08005478 sp<IBinder> responsiveToken1, responsiveToken2;
5479 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
5480 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005481
5482 // Both applications should be marked as responsive, in any order
5483 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
5484 mFocusedWindow->getToken() == responsiveToken2);
5485 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
5486 mUnfocusedWindow->getToken() == responsiveToken2);
5487 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005488}
5489
5490// If a window is already not responding, the second tap on the same window should be ignored.
5491// We should also log an error to account for the dropped event (not tested here).
5492// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
5493TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
5494 tapOnFocusedWindow();
5495 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
5496 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
5497 // Receive the events, but don't respond
5498 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
5499 ASSERT_TRUE(downEventSequenceNum);
5500 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
5501 ASSERT_TRUE(upEventSequenceNum);
5502 const std::chrono::duration timeout =
5503 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005504 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005505
5506 // Tap once again
5507 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005508 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005509 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5510 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005511 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005512 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5513 FOCUSED_WINDOW_LOCATION));
5514 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
5515 // valid touch target
5516 mUnfocusedWindow->assertNoEvents();
5517
5518 // Consume the first tap
5519 mFocusedWindow->finishEvent(*downEventSequenceNum);
5520 mFocusedWindow->finishEvent(*upEventSequenceNum);
5521 ASSERT_TRUE(mDispatcher->waitForIdle());
5522 // The second tap did not go to the focused window
5523 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005524 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08005525 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
5526 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005527 mFakePolicy->assertNotifyAnrWasNotCalled();
5528}
5529
5530// If you tap outside of all windows, there will not be ANR
5531TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005532 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005533 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5534 LOCATION_OUTSIDE_ALL_WINDOWS));
5535 ASSERT_TRUE(mDispatcher->waitForIdle());
5536 mFakePolicy->assertNotifyAnrWasNotCalled();
5537}
5538
5539// Since the focused window is paused, tapping on it should not produce any events
5540TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
5541 mFocusedWindow->setPaused(true);
5542 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
5543
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005544 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005545 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5546 FOCUSED_WINDOW_LOCATION));
5547
5548 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
5549 ASSERT_TRUE(mDispatcher->waitForIdle());
5550 // Should not ANR because the window is paused, and touches shouldn't go to it
5551 mFakePolicy->assertNotifyAnrWasNotCalled();
5552
5553 mFocusedWindow->assertNoEvents();
5554 mUnfocusedWindow->assertNoEvents();
5555}
5556
5557/**
5558 * If a window is processing a motion event, and then a key event comes in, the key event should
5559 * not to to the focused window until the motion is processed.
5560 * If a different window becomes focused at this time, the key should go to that window instead.
5561 *
5562 * Warning!!!
5563 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
5564 * and the injection timeout that we specify when injecting the key.
5565 * We must have the injection timeout (10ms) be smaller than
5566 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
5567 *
5568 * If that value changes, this test should also change.
5569 */
5570TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
5571 // Set a long ANR timeout to prevent it from triggering
5572 mFocusedWindow->setDispatchingTimeout(2s);
5573 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
5574
5575 tapOnUnfocusedWindow();
5576 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
5577 ASSERT_TRUE(downSequenceNum);
5578 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
5579 ASSERT_TRUE(upSequenceNum);
5580 // Don't finish the events yet, and send a key
5581 // Injection will succeed because we will eventually give up and send the key to the focused
5582 // window even if motions are still being processed.
5583
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005584 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005585 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005586 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
5587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005588 // Key will not be sent to the window, yet, because the window is still processing events
5589 // and the key remains pending, waiting for the touch events to be processed
5590 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
5591 ASSERT_FALSE(keySequenceNum);
5592
5593 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07005594 mFocusedWindow->setFocusable(false);
5595 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005596 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005597 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005598
5599 // Focus events should precede the key events
5600 mUnfocusedWindow->consumeFocusEvent(true);
5601 mFocusedWindow->consumeFocusEvent(false);
5602
5603 // Finish the tap events, which should unblock dispatcher
5604 mUnfocusedWindow->finishEvent(*downSequenceNum);
5605 mUnfocusedWindow->finishEvent(*upSequenceNum);
5606
5607 // Now that all queues are cleared and no backlog in the connections, the key event
5608 // can finally go to the newly focused "mUnfocusedWindow".
5609 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5610 mFocusedWindow->assertNoEvents();
5611 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005612 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005613}
5614
5615// When the touch stream is split across 2 windows, and one of them does not respond,
5616// then ANR should be raised and the touch should be canceled for the unresponsive window.
5617// The other window should not be affected by that.
5618TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
5619 // Touch Window 1
5620 NotifyMotionArgs motionArgs =
5621 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5622 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
5623 mDispatcher->notifyMotion(&motionArgs);
5624 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
5625 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
5626
5627 // Touch Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005628 motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5629 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005630 mDispatcher->notifyMotion(&motionArgs);
5631
5632 const std::chrono::duration timeout =
5633 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005634 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005635
5636 mUnfocusedWindow->consumeMotionDown();
5637 mFocusedWindow->consumeMotionDown();
5638 // Focused window may or may not receive ACTION_MOVE
5639 // But it should definitely receive ACTION_CANCEL due to the ANR
5640 InputEvent* event;
5641 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
5642 ASSERT_TRUE(moveOrCancelSequenceNum);
5643 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
5644 ASSERT_NE(nullptr, event);
5645 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
5646 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
5647 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
5648 mFocusedWindow->consumeMotionCancel();
5649 } else {
5650 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
5651 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005652 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08005653 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
5654 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005655
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005656 mUnfocusedWindow->assertNoEvents();
5657 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005658 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005659}
5660
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05005661/**
5662 * If we have no focused window, and a key comes in, we start the ANR timer.
5663 * The focused application should add a focused window before the timer runs out to prevent ANR.
5664 *
5665 * If the user touches another application during this time, the key should be dropped.
5666 * Next, if a new focused window comes in, without toggling the focused application,
5667 * then no ANR should occur.
5668 *
5669 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
5670 * but in some cases the policy may not update the focused application.
5671 */
5672TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
5673 std::shared_ptr<FakeApplicationHandle> focusedApplication =
5674 std::make_shared<FakeApplicationHandle>();
5675 focusedApplication->setDispatchingTimeout(60ms);
5676 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
5677 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
5678 mFocusedWindow->setFocusable(false);
5679
5680 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
5681 mFocusedWindow->consumeFocusEvent(false);
5682
5683 // Send a key. The ANR timer should start because there is no focused window.
5684 // 'focusedApplication' will get blamed if this timer completes.
5685 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005686 InputEventInjectionResult result =
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05005687 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005688 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
5689 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05005691
5692 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
5693 // then the injected touches won't cause the focused event to get dropped.
5694 // The dispatcher only checks for whether the queue should be pruned upon queueing.
5695 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
5696 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
5697 // For this test, it means that the key would get delivered to the window once it becomes
5698 // focused.
5699 std::this_thread::sleep_for(10ms);
5700
5701 // Touch unfocused window. This should force the pending key to get dropped.
5702 NotifyMotionArgs motionArgs =
5703 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5704 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
5705 mDispatcher->notifyMotion(&motionArgs);
5706
5707 // We do not consume the motion right away, because that would require dispatcher to first
5708 // process (== drop) the key event, and by that time, ANR will be raised.
5709 // Set the focused window first.
5710 mFocusedWindow->setFocusable(true);
5711 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
5712 setFocusedWindow(mFocusedWindow);
5713 mFocusedWindow->consumeFocusEvent(true);
5714 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
5715 // to another application. This could be a bug / behaviour in the policy.
5716
5717 mUnfocusedWindow->consumeMotionDown();
5718
5719 ASSERT_TRUE(mDispatcher->waitForIdle());
5720 // Should not ANR because we actually have a focused window. It was just added too slowly.
5721 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
5722}
5723
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05005724// These tests ensure we cannot send touch events to a window that's positioned behind a window
5725// that has feature NO_INPUT_CHANNEL.
5726// Layout:
5727// Top (closest to user)
5728// mNoInputWindow (above all windows)
5729// mBottomWindow
5730// Bottom (furthest from user)
5731class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
5732 virtual void SetUp() override {
5733 InputDispatcherTest::SetUp();
5734
5735 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005736 mNoInputWindow =
5737 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
5738 "Window without input channel", ADISPLAY_ID_DEFAULT,
5739 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08005740 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05005741 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
5742 // It's perfectly valid for this window to not have an associated input channel
5743
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005744 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
5745 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05005746 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
5747
5748 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
5749 }
5750
5751protected:
5752 std::shared_ptr<FakeApplicationHandle> mApplication;
5753 sp<FakeWindowHandle> mNoInputWindow;
5754 sp<FakeWindowHandle> mBottomWindow;
5755};
5756
5757TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
5758 PointF touchedPoint = {10, 10};
5759
5760 NotifyMotionArgs motionArgs =
5761 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5762 ADISPLAY_ID_DEFAULT, {touchedPoint});
5763 mDispatcher->notifyMotion(&motionArgs);
5764
5765 mNoInputWindow->assertNoEvents();
5766 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
5767 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
5768 // and therefore should prevent mBottomWindow from receiving touches
5769 mBottomWindow->assertNoEvents();
5770}
5771
5772/**
5773 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
5774 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
5775 */
5776TEST_F(InputDispatcherMultiWindowOcclusionTests,
5777 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005778 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
5779 "Window with input channel and NO_INPUT_CHANNEL",
5780 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05005781
Prabir Pradhan51e7db02022-02-07 06:02:57 -08005782 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05005783 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
5784 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
5785
5786 PointF touchedPoint = {10, 10};
5787
5788 NotifyMotionArgs motionArgs =
5789 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5790 ADISPLAY_ID_DEFAULT, {touchedPoint});
5791 mDispatcher->notifyMotion(&motionArgs);
5792
5793 mNoInputWindow->assertNoEvents();
5794 mBottomWindow->assertNoEvents();
5795}
5796
Vishnu Nair958da932020-08-21 17:12:37 -07005797class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
5798protected:
5799 std::shared_ptr<FakeApplicationHandle> mApp;
5800 sp<FakeWindowHandle> mWindow;
5801 sp<FakeWindowHandle> mMirror;
5802
5803 virtual void SetUp() override {
5804 InputDispatcherTest::SetUp();
5805 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005806 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
5807 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
5808 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07005809 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5810 mWindow->setFocusable(true);
5811 mMirror->setFocusable(true);
5812 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5813 }
5814};
5815
5816TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
5817 // Request focus on a mirrored window
5818 setFocusedWindow(mMirror);
5819
5820 // window gets focused
5821 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005822 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5823 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005824 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
5825}
5826
5827// A focused & mirrored window remains focused only if the window and its mirror are both
5828// focusable.
5829TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
5830 setFocusedWindow(mMirror);
5831
5832 // window gets focused
5833 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005834 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5835 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005836 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5838 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005839 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5840
5841 mMirror->setFocusable(false);
5842 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5843
5844 // window loses focus since one of the windows associated with the token in not focusable
5845 mWindow->consumeFocusEvent(false);
5846
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005847 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5848 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005849 mWindow->assertNoEvents();
5850}
5851
5852// A focused & mirrored window remains focused until the window and its mirror both become
5853// invisible.
5854TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
5855 setFocusedWindow(mMirror);
5856
5857 // window gets focused
5858 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5860 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005861 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005862 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5863 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005864 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5865
5866 mMirror->setVisible(false);
5867 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5868
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5870 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005871 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005872 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5873 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005874 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5875
5876 mWindow->setVisible(false);
5877 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5878
5879 // window loses focus only after all windows associated with the token become invisible.
5880 mWindow->consumeFocusEvent(false);
5881
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005882 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5883 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005884 mWindow->assertNoEvents();
5885}
5886
5887// A focused & mirrored window remains focused until both windows are removed.
5888TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
5889 setFocusedWindow(mMirror);
5890
5891 // window gets focused
5892 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5894 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005895 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5897 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005898 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5899
5900 // single window is removed but the window token remains focused
5901 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
5902
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5904 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005905 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5907 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005908 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5909
5910 // Both windows are removed
5911 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
5912 mWindow->consumeFocusEvent(false);
5913
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005914 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5915 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005916 mWindow->assertNoEvents();
5917}
5918
5919// Focus request can be pending until one window becomes visible.
5920TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
5921 // Request focus on an invisible mirror.
5922 mWindow->setVisible(false);
5923 mMirror->setVisible(false);
5924 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5925 setFocusedWindow(mMirror);
5926
5927 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005928 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07005929 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005930 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005931
5932 mMirror->setVisible(true);
5933 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5934
5935 // window gets focused
5936 mWindow->consumeFocusEvent(true);
5937 // window gets the pending key event
5938 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5939}
Prabir Pradhan99987712020-11-10 18:43:05 -08005940
5941class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
5942protected:
5943 std::shared_ptr<FakeApplicationHandle> mApp;
5944 sp<FakeWindowHandle> mWindow;
5945 sp<FakeWindowHandle> mSecondWindow;
5946
5947 void SetUp() override {
5948 InputDispatcherTest::SetUp();
5949 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005950 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08005951 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005952 mSecondWindow =
5953 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08005954 mSecondWindow->setFocusable(true);
5955
5956 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5957 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
5958
5959 setFocusedWindow(mWindow);
5960 mWindow->consumeFocusEvent(true);
5961 }
5962
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005963 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
5964 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005965 mDispatcher->notifyPointerCaptureChanged(&args);
5966 }
5967
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005968 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
5969 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08005970 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005971 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
5972 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005973 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005974 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08005975 }
5976};
5977
5978TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
5979 // Ensure that capture cannot be obtained for unfocused windows.
5980 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
5981 mFakePolicy->assertSetPointerCaptureNotCalled();
5982 mSecondWindow->assertNoEvents();
5983
5984 // Ensure that capture can be enabled from the focus window.
5985 requestAndVerifyPointerCapture(mWindow, true);
5986
5987 // Ensure that capture cannot be disabled from a window that does not have capture.
5988 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
5989 mFakePolicy->assertSetPointerCaptureNotCalled();
5990
5991 // Ensure that capture can be disabled from the window with capture.
5992 requestAndVerifyPointerCapture(mWindow, false);
5993}
5994
5995TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005996 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08005997
5998 setFocusedWindow(mSecondWindow);
5999
6000 // Ensure that the capture disabled event was sent first.
6001 mWindow->consumeCaptureEvent(false);
6002 mWindow->consumeFocusEvent(false);
6003 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006004 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08006005
6006 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006007 notifyPointerCaptureChanged({});
6008 notifyPointerCaptureChanged(request);
6009 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08006010 mWindow->assertNoEvents();
6011 mSecondWindow->assertNoEvents();
6012 mFakePolicy->assertSetPointerCaptureNotCalled();
6013}
6014
6015TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006016 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08006017
6018 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006019 notifyPointerCaptureChanged({});
6020 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08006021
6022 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006023 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08006024 mWindow->consumeCaptureEvent(false);
6025 mWindow->assertNoEvents();
6026}
6027
Prabir Pradhan167e6d92021-02-04 16:18:17 -08006028TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
6029 requestAndVerifyPointerCapture(mWindow, true);
6030
6031 // The first window loses focus.
6032 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006033 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08006034 mWindow->consumeCaptureEvent(false);
6035
6036 // Request Pointer Capture from the second window before the notification from InputReader
6037 // arrives.
6038 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006039 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08006040
6041 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006042 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08006043
6044 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006045 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08006046
6047 mSecondWindow->consumeFocusEvent(true);
6048 mSecondWindow->consumeCaptureEvent(true);
6049}
6050
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006051TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
6052 // App repeatedly enables and disables capture.
6053 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
6054 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
6055 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
6056 mFakePolicy->assertSetPointerCaptureCalled(false);
6057 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
6058 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
6059
6060 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
6061 // first request is now stale, this should do nothing.
6062 notifyPointerCaptureChanged(firstRequest);
6063 mWindow->assertNoEvents();
6064
6065 // InputReader notifies that the second request was enabled.
6066 notifyPointerCaptureChanged(secondRequest);
6067 mWindow->consumeCaptureEvent(true);
6068}
6069
Prabir Pradhan7092e262022-05-03 16:51:09 +00006070TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
6071 requestAndVerifyPointerCapture(mWindow, true);
6072
6073 // App toggles pointer capture off and on.
6074 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
6075 mFakePolicy->assertSetPointerCaptureCalled(false);
6076
6077 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
6078 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
6079
6080 // InputReader notifies that the latest "enable" request was processed, while skipping over the
6081 // preceding "disable" request.
6082 notifyPointerCaptureChanged(enableRequest);
6083
6084 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
6085 // any notifications.
6086 mWindow->assertNoEvents();
6087}
6088
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006089class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
6090protected:
6091 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00006092
6093 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
6094 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
6095
6096 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
6097 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
6098
6099 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
6100 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
6101 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
6102 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
6103 MAXIMUM_OBSCURING_OPACITY);
6104
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006105 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006106 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006107 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006108
6109 sp<FakeWindowHandle> mTouchWindow;
6110
6111 virtual void SetUp() override {
6112 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006113 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006114 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
6115 }
6116
6117 virtual void TearDown() override {
6118 InputDispatcherTest::TearDown();
6119 mTouchWindow.clear();
6120 }
6121
chaviw3277faf2021-05-19 16:45:23 -05006122 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
6123 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006124 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006125 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006126 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006127 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006128 return window;
6129 }
6130
6131 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
6132 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
6133 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006134 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006135 // Generate an arbitrary PID based on the UID
6136 window->setOwnerInfo(1777 + (uid % 10000), uid);
6137 return window;
6138 }
6139
6140 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
6141 NotifyMotionArgs args =
6142 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6143 ADISPLAY_ID_DEFAULT, points);
6144 mDispatcher->notifyMotion(&args);
6145 }
6146};
6147
6148TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006149 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006150 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006151 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006152
6153 touch();
6154
6155 mTouchWindow->assertNoEvents();
6156}
6157
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006158TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00006159 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
6160 const sp<FakeWindowHandle>& w =
6161 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
6162 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6163
6164 touch();
6165
6166 mTouchWindow->assertNoEvents();
6167}
6168
6169TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006170 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
6171 const sp<FakeWindowHandle>& w =
6172 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
6173 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6174
6175 touch();
6176
6177 w->assertNoEvents();
6178}
6179
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006180TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006181 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
6182 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006183
6184 touch();
6185
6186 mTouchWindow->consumeAnyMotionDown();
6187}
6188
6189TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006190 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006191 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006192 w->setFrame(Rect(0, 0, 50, 50));
6193 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006194
6195 touch({PointF{100, 100}});
6196
6197 mTouchWindow->consumeAnyMotionDown();
6198}
6199
6200TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006201 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006202 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006203 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6204
6205 touch();
6206
6207 mTouchWindow->consumeAnyMotionDown();
6208}
6209
6210TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
6211 const sp<FakeWindowHandle>& w =
6212 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
6213 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006214
6215 touch();
6216
6217 mTouchWindow->consumeAnyMotionDown();
6218}
6219
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006220TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
6221 const sp<FakeWindowHandle>& w =
6222 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
6223 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6224
6225 touch();
6226
6227 w->assertNoEvents();
6228}
6229
6230/**
6231 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
6232 * inside) while letting them pass-through. Note that even though touch passes through the occluding
6233 * window, the occluding window will still receive ACTION_OUTSIDE event.
6234 */
6235TEST_F(InputDispatcherUntrustedTouchesTest,
6236 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
6237 const sp<FakeWindowHandle>& w =
6238 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006239 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006240 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6241
6242 touch();
6243
6244 w->consumeMotionOutside();
6245}
6246
6247TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
6248 const sp<FakeWindowHandle>& w =
6249 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006250 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006251 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6252
6253 touch();
6254
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08006255 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006256}
6257
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006258TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006259 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006260 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6261 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006262 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6263
6264 touch();
6265
6266 mTouchWindow->consumeAnyMotionDown();
6267}
6268
6269TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
6270 const sp<FakeWindowHandle>& w =
6271 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6272 MAXIMUM_OBSCURING_OPACITY);
6273 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006274
6275 touch();
6276
6277 mTouchWindow->consumeAnyMotionDown();
6278}
6279
6280TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006281 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006282 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6283 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006284 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6285
6286 touch();
6287
6288 mTouchWindow->assertNoEvents();
6289}
6290
6291TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
6292 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
6293 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006294 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
6295 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006296 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006297 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
6298 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006299 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
6300
6301 touch();
6302
6303 mTouchWindow->assertNoEvents();
6304}
6305
6306TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
6307 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
6308 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006309 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
6310 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006311 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006312 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
6313 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006314 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
6315
6316 touch();
6317
6318 mTouchWindow->consumeAnyMotionDown();
6319}
6320
6321TEST_F(InputDispatcherUntrustedTouchesTest,
6322 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
6323 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006324 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6325 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006326 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006327 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
6328 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006329 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
6330
6331 touch();
6332
6333 mTouchWindow->consumeAnyMotionDown();
6334}
6335
6336TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
6337 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006338 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6339 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006340 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006341 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
6342 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006343 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006344
6345 touch();
6346
6347 mTouchWindow->assertNoEvents();
6348}
6349
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006350TEST_F(InputDispatcherUntrustedTouchesTest,
6351 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
6352 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006353 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
6354 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006355 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006356 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6357 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006358 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
6359
6360 touch();
6361
6362 mTouchWindow->assertNoEvents();
6363}
6364
6365TEST_F(InputDispatcherUntrustedTouchesTest,
6366 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
6367 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006368 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
6369 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006370 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006371 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6372 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006373 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
6374
6375 touch();
6376
6377 mTouchWindow->consumeAnyMotionDown();
6378}
6379
6380TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
6381 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006382 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
6383 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006384 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6385
6386 touch();
6387
6388 mTouchWindow->consumeAnyMotionDown();
6389}
6390
6391TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
6392 const sp<FakeWindowHandle>& w =
6393 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
6394 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6395
6396 touch();
6397
6398 mTouchWindow->consumeAnyMotionDown();
6399}
6400
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00006401TEST_F(InputDispatcherUntrustedTouchesTest,
6402 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
6403 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
6404 const sp<FakeWindowHandle>& w =
6405 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
6406 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6407
6408 touch();
6409
6410 mTouchWindow->assertNoEvents();
6411}
6412
6413TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
6414 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
6415 const sp<FakeWindowHandle>& w =
6416 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
6417 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6418
6419 touch();
6420
6421 mTouchWindow->consumeAnyMotionDown();
6422}
6423
6424TEST_F(InputDispatcherUntrustedTouchesTest,
6425 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
6426 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
6427 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006428 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6429 OPACITY_ABOVE_THRESHOLD);
6430 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6431
6432 touch();
6433
6434 mTouchWindow->consumeAnyMotionDown();
6435}
6436
6437TEST_F(InputDispatcherUntrustedTouchesTest,
6438 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
6439 const sp<FakeWindowHandle>& w1 =
6440 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
6441 OPACITY_BELOW_THRESHOLD);
6442 const sp<FakeWindowHandle>& w2 =
6443 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6444 OPACITY_BELOW_THRESHOLD);
6445 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
6446
6447 touch();
6448
6449 mTouchWindow->assertNoEvents();
6450}
6451
6452/**
6453 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
6454 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
6455 * (which alone would result in allowing touches) does not affect the blocking behavior.
6456 */
6457TEST_F(InputDispatcherUntrustedTouchesTest,
6458 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
6459 const sp<FakeWindowHandle>& wB =
6460 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
6461 OPACITY_BELOW_THRESHOLD);
6462 const sp<FakeWindowHandle>& wC =
6463 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
6464 OPACITY_BELOW_THRESHOLD);
6465 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
6466
6467 touch();
6468
6469 mTouchWindow->assertNoEvents();
6470}
6471
6472/**
6473 * This test is testing that a window from a different UID but with same application token doesn't
6474 * block the touch. Apps can share the application token for close UI collaboration for example.
6475 */
6476TEST_F(InputDispatcherUntrustedTouchesTest,
6477 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
6478 const sp<FakeWindowHandle>& w =
6479 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
6480 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00006481 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6482
6483 touch();
6484
6485 mTouchWindow->consumeAnyMotionDown();
6486}
6487
arthurhungb89ccb02020-12-30 16:19:01 +08006488class InputDispatcherDragTests : public InputDispatcherTest {
6489protected:
6490 std::shared_ptr<FakeApplicationHandle> mApp;
6491 sp<FakeWindowHandle> mWindow;
6492 sp<FakeWindowHandle> mSecondWindow;
6493 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006494 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006495 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
6496 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08006497
6498 void SetUp() override {
6499 InputDispatcherTest::SetUp();
6500 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006501 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08006502 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08006503
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006504 mSecondWindow =
6505 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08006506 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08006507
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006508 mSpyWindow =
6509 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006510 mSpyWindow->setSpy(true);
6511 mSpyWindow->setTrustedOverlay(true);
6512 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
6513
arthurhungb89ccb02020-12-30 16:19:01 +08006514 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006515 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08006516 }
6517
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006518 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
6519 switch (fromSource) {
6520 case AINPUT_SOURCE_TOUCHSCREEN:
6521 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6522 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6523 ADISPLAY_ID_DEFAULT, {50, 50}))
6524 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6525 break;
6526 case AINPUT_SOURCE_STYLUS:
6527 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6528 injectMotionEvent(
6529 mDispatcher,
6530 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
6531 AINPUT_SOURCE_STYLUS)
6532 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
6533 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
6534 .x(50)
6535 .y(50))
6536 .build()));
6537 break;
6538 case AINPUT_SOURCE_MOUSE:
6539 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6540 injectMotionEvent(
6541 mDispatcher,
6542 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6543 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
6544 .pointer(PointerBuilder(MOUSE_POINTER_ID,
6545 AMOTION_EVENT_TOOL_TYPE_MOUSE)
6546 .x(50)
6547 .y(50))
6548 .build()));
6549 break;
6550 default:
6551 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
6552 }
arthurhungb89ccb02020-12-30 16:19:01 +08006553
6554 // Window should receive motion event.
6555 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006556 // Spy window should also receive motion event
6557 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00006558 }
6559
6560 // Start performing drag, we will create a drag window and transfer touch to it.
6561 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
6562 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006563 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00006564 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006565 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00006566 }
arthurhungb89ccb02020-12-30 16:19:01 +08006567
6568 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006569 mDragWindow =
6570 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006571 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08006572 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006573 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08006574
6575 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00006576 bool transferred =
6577 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
6578 true /* isDragDrop */);
6579 if (transferred) {
6580 mWindow->consumeMotionCancel();
6581 mDragWindow->consumeMotionDown();
6582 }
6583 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08006584 }
6585};
6586
6587TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006588 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08006589
6590 // Move on window.
6591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6592 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6593 ADISPLAY_ID_DEFAULT, {50, 50}))
6594 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6595 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6596 mWindow->consumeDragEvent(false, 50, 50);
6597 mSecondWindow->assertNoEvents();
6598
6599 // Move to another window.
6600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6601 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6602 ADISPLAY_ID_DEFAULT, {150, 50}))
6603 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6604 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6605 mWindow->consumeDragEvent(true, 150, 50);
6606 mSecondWindow->consumeDragEvent(false, 50, 50);
6607
6608 // Move back to original window.
6609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6610 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6611 ADISPLAY_ID_DEFAULT, {50, 50}))
6612 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6613 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6614 mWindow->consumeDragEvent(false, 50, 50);
6615 mSecondWindow->consumeDragEvent(true, -50, 50);
6616
6617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6618 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
6619 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6620 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6621 mWindow->assertNoEvents();
6622 mSecondWindow->assertNoEvents();
6623}
6624
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006625TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006626 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006627
6628 // No cancel event after drag start
6629 mSpyWindow->assertNoEvents();
6630
6631 const MotionEvent secondFingerDownEvent =
6632 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6633 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6634 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6635 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(60).y(60))
6636 .build();
6637 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6638 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
6639 InputEventInjectionSync::WAIT_FOR_RESULT))
6640 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6641
6642 // Receives cancel for first pointer after next pointer down
6643 mSpyWindow->consumeMotionCancel();
6644 mSpyWindow->consumeMotionDown();
6645
6646 mSpyWindow->assertNoEvents();
6647}
6648
arthurhungf452d0b2021-01-06 00:19:52 +08006649TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006650 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08006651
6652 // Move on window.
6653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6654 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6655 ADISPLAY_ID_DEFAULT, {50, 50}))
6656 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6657 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6658 mWindow->consumeDragEvent(false, 50, 50);
6659 mSecondWindow->assertNoEvents();
6660
6661 // Move to another window.
6662 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6663 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6664 ADISPLAY_ID_DEFAULT, {150, 50}))
6665 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6666 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6667 mWindow->consumeDragEvent(true, 150, 50);
6668 mSecondWindow->consumeDragEvent(false, 50, 50);
6669
6670 // drop to another window.
6671 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6672 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6673 {150, 50}))
6674 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6675 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6676 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
6677 mWindow->assertNoEvents();
6678 mSecondWindow->assertNoEvents();
6679}
6680
arthurhung6d4bed92021-03-17 11:59:33 +08006681TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006682 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08006683
6684 // Move on window and keep button pressed.
6685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6686 injectMotionEvent(mDispatcher,
6687 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
6688 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
6689 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
6690 .x(50)
6691 .y(50))
6692 .build()))
6693 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6694 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6695 mWindow->consumeDragEvent(false, 50, 50);
6696 mSecondWindow->assertNoEvents();
6697
6698 // Move to another window and release button, expect to drop item.
6699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6700 injectMotionEvent(mDispatcher,
6701 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
6702 .buttonState(0)
6703 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
6704 .x(150)
6705 .y(50))
6706 .build()))
6707 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6708 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6709 mWindow->assertNoEvents();
6710 mSecondWindow->assertNoEvents();
6711 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
6712
6713 // nothing to the window.
6714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6715 injectMotionEvent(mDispatcher,
6716 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
6717 .buttonState(0)
6718 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
6719 .x(150)
6720 .y(50))
6721 .build()))
6722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6723 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6724 mWindow->assertNoEvents();
6725 mSecondWindow->assertNoEvents();
6726}
6727
Arthur Hung54745652022-04-20 07:17:41 +00006728TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006729 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08006730
6731 // Set second window invisible.
6732 mSecondWindow->setVisible(false);
6733 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
6734
6735 // Move on window.
6736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6737 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6738 ADISPLAY_ID_DEFAULT, {50, 50}))
6739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6740 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6741 mWindow->consumeDragEvent(false, 50, 50);
6742 mSecondWindow->assertNoEvents();
6743
6744 // Move to another window.
6745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6746 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6747 ADISPLAY_ID_DEFAULT, {150, 50}))
6748 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6749 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6750 mWindow->consumeDragEvent(true, 150, 50);
6751 mSecondWindow->assertNoEvents();
6752
6753 // drop to another window.
6754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6755 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6756 {150, 50}))
6757 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6758 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6759 mFakePolicy->assertDropTargetEquals(nullptr);
6760 mWindow->assertNoEvents();
6761 mSecondWindow->assertNoEvents();
6762}
6763
Arthur Hung54745652022-04-20 07:17:41 +00006764TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006765 // Ensure window could track pointerIds if it didn't support split touch.
6766 mWindow->setPreventSplitting(true);
6767
Arthur Hung54745652022-04-20 07:17:41 +00006768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6769 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6770 {50, 50}))
6771 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6772 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6773
6774 const MotionEvent secondFingerDownEvent =
6775 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6776 .displayId(ADISPLAY_ID_DEFAULT)
6777 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6778 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6779 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(75).y(50))
6780 .build();
6781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6782 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
6783 InputEventInjectionSync::WAIT_FOR_RESULT))
6784 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6785 mWindow->consumeMotionPointerDown(1 /* pointerIndex */);
6786
6787 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006788 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00006789}
6790
6791TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
6792 // First down on second window.
6793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6794 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6795 {150, 50}))
6796 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6797
6798 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6799
6800 // Second down on first window.
6801 const MotionEvent secondFingerDownEvent =
6802 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6803 .displayId(ADISPLAY_ID_DEFAULT)
6804 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6805 .pointer(
6806 PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
6807 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6808 .build();
6809 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6810 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
6811 InputEventInjectionSync::WAIT_FOR_RESULT))
6812 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6813 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6814
6815 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006816 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00006817
6818 // Move on window.
6819 const MotionEvent secondFingerMoveEvent =
6820 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6821 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6822 .pointer(
6823 PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
6824 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6825 .build();
6826 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6827 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
6828 InputEventInjectionSync::WAIT_FOR_RESULT));
6829 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6830 mWindow->consumeDragEvent(false, 50, 50);
6831 mSecondWindow->consumeMotionMove();
6832
6833 // Release the drag pointer should perform drop.
6834 const MotionEvent secondFingerUpEvent =
6835 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
6836 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6837 .pointer(
6838 PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
6839 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6840 .build();
6841 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6842 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
6843 InputEventInjectionSync::WAIT_FOR_RESULT));
6844 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6845 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
6846 mWindow->assertNoEvents();
6847 mSecondWindow->consumeMotionMove();
6848}
6849
Arthur Hung3915c1f2022-05-31 07:17:17 +00006850TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006851 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00006852
6853 // Update window of second display.
6854 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006855 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00006856 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
6857
6858 // Let second display has a touch state.
6859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6860 injectMotionEvent(mDispatcher,
6861 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
6862 AINPUT_SOURCE_TOUCHSCREEN)
6863 .displayId(SECOND_DISPLAY_ID)
6864 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
6865 .x(100)
6866 .y(100))
6867 .build()));
6868 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
6869 SECOND_DISPLAY_ID, 0 /* expectedFlag */);
6870 // Update window again.
6871 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
6872
6873 // Move on window.
6874 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6875 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6876 ADISPLAY_ID_DEFAULT, {50, 50}))
6877 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6878 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6879 mWindow->consumeDragEvent(false, 50, 50);
6880 mSecondWindow->assertNoEvents();
6881
6882 // Move to another window.
6883 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6884 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6885 ADISPLAY_ID_DEFAULT, {150, 50}))
6886 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6887 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6888 mWindow->consumeDragEvent(true, 150, 50);
6889 mSecondWindow->consumeDragEvent(false, 50, 50);
6890
6891 // drop to another window.
6892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6893 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6894 {150, 50}))
6895 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6896 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6897 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
6898 mWindow->assertNoEvents();
6899 mSecondWindow->assertNoEvents();
6900}
6901
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006902TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
6903 startDrag(true, AINPUT_SOURCE_MOUSE);
6904 // Move on window.
6905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6906 injectMotionEvent(mDispatcher,
6907 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
6908 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
6909 .pointer(PointerBuilder(MOUSE_POINTER_ID,
6910 AMOTION_EVENT_TOOL_TYPE_MOUSE)
6911 .x(50)
6912 .y(50))
6913 .build()))
6914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6915 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6916 mWindow->consumeDragEvent(false, 50, 50);
6917 mSecondWindow->assertNoEvents();
6918
6919 // Move to another window.
6920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6921 injectMotionEvent(mDispatcher,
6922 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
6923 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
6924 .pointer(PointerBuilder(MOUSE_POINTER_ID,
6925 AMOTION_EVENT_TOOL_TYPE_MOUSE)
6926 .x(150)
6927 .y(50))
6928 .build()))
6929 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6930 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6931 mWindow->consumeDragEvent(true, 150, 50);
6932 mSecondWindow->consumeDragEvent(false, 50, 50);
6933
6934 // drop to another window.
6935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6936 injectMotionEvent(mDispatcher,
6937 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
6938 .buttonState(0)
6939 .pointer(PointerBuilder(MOUSE_POINTER_ID,
6940 AMOTION_EVENT_TOOL_TYPE_MOUSE)
6941 .x(150)
6942 .y(50))
6943 .build()))
6944 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6945 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6946 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
6947 mWindow->assertNoEvents();
6948 mSecondWindow->assertNoEvents();
6949}
6950
Vishnu Nair062a8672021-09-03 16:07:44 -07006951class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
6952
6953TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
6954 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006955 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6956 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006957 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07006958 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6959 window->setFocusable(true);
6960 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
6961 setFocusedWindow(window);
6962 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
6963
6964 // With the flag set, window should not get any input
6965 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
6966 mDispatcher->notifyKey(&keyArgs);
6967 window->assertNoEvents();
6968
6969 NotifyMotionArgs motionArgs =
6970 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6971 ADISPLAY_ID_DEFAULT);
6972 mDispatcher->notifyMotion(&motionArgs);
6973 window->assertNoEvents();
6974
6975 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006976 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07006977 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
6978
6979 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
6980 mDispatcher->notifyKey(&keyArgs);
6981 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
6982
6983 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6984 ADISPLAY_ID_DEFAULT);
6985 mDispatcher->notifyMotion(&motionArgs);
6986 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6987 window->assertNoEvents();
6988}
6989
6990TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
6991 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
6992 std::make_shared<FakeApplicationHandle>();
6993 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006994 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
6995 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07006996 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
6997 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006998 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07006999 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007000 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
7001 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007002 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07007003 window->setOwnerInfo(222, 222);
7004 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7005 window->setFocusable(true);
7006 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
7007 setFocusedWindow(window);
7008 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
7009
7010 // With the flag set, window should not get any input
7011 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
7012 mDispatcher->notifyKey(&keyArgs);
7013 window->assertNoEvents();
7014
7015 NotifyMotionArgs motionArgs =
7016 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7017 ADISPLAY_ID_DEFAULT);
7018 mDispatcher->notifyMotion(&motionArgs);
7019 window->assertNoEvents();
7020
7021 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007022 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07007023 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
7024
7025 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
7026 mDispatcher->notifyKey(&keyArgs);
7027 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
7028
7029 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7030 ADISPLAY_ID_DEFAULT);
7031 mDispatcher->notifyMotion(&motionArgs);
7032 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
7033 window->assertNoEvents();
7034}
7035
7036TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
7037 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
7038 std::make_shared<FakeApplicationHandle>();
7039 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007040 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
7041 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07007042 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
7043 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007044 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07007045 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007046 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
7047 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007048 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07007049 window->setOwnerInfo(222, 222);
7050 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7051 window->setFocusable(true);
7052 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
7053 setFocusedWindow(window);
7054 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
7055
7056 // With the flag set, window should not get any input
7057 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
7058 mDispatcher->notifyKey(&keyArgs);
7059 window->assertNoEvents();
7060
7061 NotifyMotionArgs motionArgs =
7062 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7063 ADISPLAY_ID_DEFAULT);
7064 mDispatcher->notifyMotion(&motionArgs);
7065 window->assertNoEvents();
7066
7067 // When the window is no longer obscured because it went on top, it should get input
7068 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
7069
7070 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
7071 mDispatcher->notifyKey(&keyArgs);
7072 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
7073
7074 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7075 ADISPLAY_ID_DEFAULT);
7076 mDispatcher->notifyMotion(&motionArgs);
7077 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7078 window->assertNoEvents();
7079}
7080
Antonio Kantekf16f2832021-09-28 04:39:20 +00007081class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
7082protected:
7083 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00007084 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00007085 sp<FakeWindowHandle> mWindow;
7086 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00007087 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00007088
7089 void SetUp() override {
7090 InputDispatcherTest::SetUp();
7091
7092 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00007093 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007094 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007095 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00007096 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007097 mSecondWindow =
7098 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007099 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00007100 mThirdWindow =
7101 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
7102 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
7103 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007104
7105 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00007106 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
7107 {SECOND_DISPLAY_ID, {mThirdWindow}}});
7108 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007109 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00007110
Antonio Kantek15beb512022-06-13 22:35:41 +00007111 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00007112 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Antonio Kantek15beb512022-06-13 22:35:41 +00007113 WINDOW_UID, true /* hasPermission */,
7114 ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07007115 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
7116 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00007117 mThirdWindow->assertNoEvents();
7118 }
7119
7120 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
7121 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
7122 SECONDARY_WINDOW_UID, true /* hasPermission */,
7123 SECOND_DISPLAY_ID)) {
7124 mWindow->assertNoEvents();
7125 mSecondWindow->assertNoEvents();
7126 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07007127 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00007128 }
7129
Antonio Kantek15beb512022-06-13 22:35:41 +00007130 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid,
7131 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07007132 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
7133 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00007134 mWindow->consumeTouchModeEvent(inTouchMode);
7135 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00007136 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00007137 }
7138};
7139
Antonio Kantek26defcf2022-02-08 01:12:27 +00007140TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08007141 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00007142 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
7143 windowInfo.ownerPid, windowInfo.ownerUid,
7144 false /* hasPermission */);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007145}
7146
Antonio Kantek26defcf2022-02-08 01:12:27 +00007147TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
7148 const WindowInfo& windowInfo = *mWindow->getInfo();
7149 int32_t ownerPid = windowInfo.ownerPid;
7150 int32_t ownerUid = windowInfo.ownerUid;
7151 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
7152 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Antonio Kanteka042c022022-07-06 16:51:07 -07007153 ownerUid, false /*hasPermission*/,
7154 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00007155 mWindow->assertNoEvents();
7156 mSecondWindow->assertNoEvents();
7157}
7158
7159TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
7160 const WindowInfo& windowInfo = *mWindow->getInfo();
7161 int32_t ownerPid = windowInfo.ownerPid;
7162 int32_t ownerUid = windowInfo.ownerUid;
7163 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
Antonio Kantek15beb512022-06-13 22:35:41 +00007164 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
7165 ownerUid, true /*hasPermission*/);
Antonio Kantek26defcf2022-02-08 01:12:27 +00007166}
7167
Antonio Kantekf16f2832021-09-28 04:39:20 +00007168TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08007169 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00007170 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
7171 windowInfo.ownerPid, windowInfo.ownerUid,
Antonio Kanteka042c022022-07-06 16:51:07 -07007172 true /*hasPermission*/, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00007173 mWindow->assertNoEvents();
7174 mSecondWindow->assertNoEvents();
7175}
7176
Antonio Kantek15beb512022-06-13 22:35:41 +00007177TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
7178 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
7179 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
7180 windowInfo.ownerPid, windowInfo.ownerUid,
7181 true /*hasPermission*/, SECOND_DISPLAY_ID));
7182 mWindow->assertNoEvents();
7183 mSecondWindow->assertNoEvents();
7184 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
7185}
7186
Antonio Kantek48710e42022-03-24 14:19:30 -07007187TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
7188 // Interact with the window first.
7189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
7190 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
7191 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7192
7193 // Then remove focus.
7194 mWindow->setFocusable(false);
7195 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7196
7197 // Assert that caller can switch touch mode by owning one of the last interacted window.
7198 const WindowInfo& windowInfo = *mWindow->getInfo();
7199 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
7200 windowInfo.ownerPid, windowInfo.ownerUid,
Antonio Kanteka042c022022-07-06 16:51:07 -07007201 false /*hasPermission*/, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07007202}
7203
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007204class InputDispatcherSpyWindowTest : public InputDispatcherTest {
7205public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007206 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007207 std::shared_ptr<FakeApplicationHandle> application =
7208 std::make_shared<FakeApplicationHandle>();
7209 std::string name = "Fake Spy ";
7210 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007211 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
7212 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007213 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08007214 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007215 return spy;
7216 }
7217
7218 sp<FakeWindowHandle> createForeground() {
7219 std::shared_ptr<FakeApplicationHandle> application =
7220 std::make_shared<FakeApplicationHandle>();
7221 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007222 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7223 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007224 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007225 return window;
7226 }
7227
7228private:
7229 int mSpyCount{0};
7230};
7231
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08007232using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007233/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08007234 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
7235 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08007236TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
7237 ScopedSilentDeath _silentDeath;
7238
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007239 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08007240 spy->setTrustedOverlay(false);
7241 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
7242 ".* not a trusted overlay");
7243}
7244
7245/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007246 * Input injection into a display with a spy window but no foreground windows should succeed.
7247 */
7248TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007249 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007250 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
7251
7252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7253 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7254 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7255 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7256}
7257
7258/**
7259 * Verify the order in which different input windows receive events. The touched foreground window
7260 * (if there is one) should always receive the event first. When there are multiple spy windows, the
7261 * spy windows will receive the event according to their Z-order, where the top-most spy window will
7262 * receive events before ones belows it.
7263 *
7264 * Here, we set up a scenario with four windows in the following Z order from the top:
7265 * spy1, spy2, window, spy3.
7266 * We then inject an event and verify that the foreground "window" receives it first, followed by
7267 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
7268 * window.
7269 */
7270TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
7271 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007272 auto spy1 = createSpy();
7273 auto spy2 = createSpy();
7274 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007275 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
7276 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
7277 const size_t numChannels = channels.size();
7278
Michael Wright8e9a8562022-02-09 13:44:29 +00007279 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007280 if (!epollFd.ok()) {
7281 FAIL() << "Failed to create epoll fd";
7282 }
7283
7284 for (size_t i = 0; i < numChannels; i++) {
7285 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
7286 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
7287 FAIL() << "Failed to add fd to epoll";
7288 }
7289 }
7290
7291 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7292 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7293 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7294
7295 std::vector<size_t> eventOrder;
7296 std::vector<struct epoll_event> events(numChannels);
7297 for (;;) {
7298 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
7299 (100ms).count());
7300 if (nFds < 0) {
7301 FAIL() << "Failed to call epoll_wait";
7302 }
7303 if (nFds == 0) {
7304 break; // epoll_wait timed out
7305 }
7306 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07007307 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07007308 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007309 channels[i]->consumeMotionDown();
7310 }
7311 }
7312
7313 // Verify the order in which the events were received.
7314 EXPECT_EQ(3u, eventOrder.size());
7315 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
7316 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
7317 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
7318}
7319
7320/**
7321 * A spy window using the NOT_TOUCHABLE flag does not receive events.
7322 */
7323TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
7324 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007325 auto spy = createSpy();
7326 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007327 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7328
7329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7330 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7331 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7332 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7333 spy->assertNoEvents();
7334}
7335
7336/**
7337 * A spy window will only receive gestures that originate within its touchable region. Gestures that
7338 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
7339 * to the window.
7340 */
7341TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
7342 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007343 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007344 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
7345 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7346
7347 // Inject an event outside the spy window's touchable region.
7348 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7349 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7350 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7351 window->consumeMotionDown();
7352 spy->assertNoEvents();
7353 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7354 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7355 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7356 window->consumeMotionUp();
7357 spy->assertNoEvents();
7358
7359 // Inject an event inside the spy window's touchable region.
7360 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7361 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7362 {5, 10}))
7363 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7364 window->consumeMotionDown();
7365 spy->consumeMotionDown();
7366}
7367
7368/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007369 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007370 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007371 */
7372TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
7373 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007374 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007375 auto spy = createSpy();
7376 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007377 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007378 spy->setFrame(Rect{0, 0, 20, 20});
7379 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7380
7381 // Inject an event outside the spy window's frame and touchable region.
7382 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007383 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7384 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007385 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7386 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007387 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007388}
7389
7390/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007391 * Even when a spy window spans over multiple foreground windows, the spy should receive all
7392 * pointers that are down within its bounds.
7393 */
7394TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
7395 auto windowLeft = createForeground();
7396 windowLeft->setFrame({0, 0, 100, 200});
7397 auto windowRight = createForeground();
7398 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007399 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007400 spy->setFrame({0, 0, 200, 200});
7401 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
7402
7403 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7404 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7405 {50, 50}))
7406 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7407 windowLeft->consumeMotionDown();
7408 spy->consumeMotionDown();
7409
7410 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007411 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007412 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7413 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7414 .pointer(
7415 PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
7416 .build();
7417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7418 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7419 InputEventInjectionSync::WAIT_FOR_RESULT))
7420 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7421 windowRight->consumeMotionDown();
7422 spy->consumeMotionPointerDown(1 /*pointerIndex*/);
7423}
7424
7425/**
7426 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
7427 * the spy should receive the second pointer with ACTION_DOWN.
7428 */
7429TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
7430 auto window = createForeground();
7431 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007432 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007433 spyRight->setFrame({100, 0, 200, 200});
7434 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
7435
7436 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7437 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7438 {50, 50}))
7439 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7440 window->consumeMotionDown();
7441 spyRight->assertNoEvents();
7442
7443 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007444 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007445 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7446 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7447 .pointer(
7448 PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
7449 .build();
7450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7451 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7452 InputEventInjectionSync::WAIT_FOR_RESULT))
7453 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7454 window->consumeMotionPointerDown(1 /*pointerIndex*/);
7455 spyRight->consumeMotionDown();
7456}
7457
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007458/**
7459 * The spy window should not be able to affect whether or not touches are split. Only the foreground
7460 * windows should be allowed to control split touch.
7461 */
7462TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007463 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007464 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007465 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007466 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007467
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007468 auto window = createForeground();
7469 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007470
7471 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7472
7473 // First finger down, no window touched.
7474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7475 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7476 {100, 200}))
7477 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7478 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7479 window->assertNoEvents();
7480
7481 // Second finger down on window, the window should receive touch down.
7482 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007483 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007484 .displayId(ADISPLAY_ID_DEFAULT)
7485 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7486 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
7487 .x(100)
7488 .y(200))
7489 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7490 .build();
7491 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7492 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7493 InputEventInjectionSync::WAIT_FOR_RESULT))
7494 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7495
7496 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7497 spy->consumeMotionPointerDown(1 /* pointerIndex */);
7498}
7499
7500/**
7501 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
7502 * do not receive key events.
7503 */
7504TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007505 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007506 spy->setFocusable(false);
7507
7508 auto window = createForeground();
7509 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7510 setFocusedWindow(window);
7511 window->consumeFocusEvent(true);
7512
7513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7514 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
7515 window->consumeKeyDown(ADISPLAY_ID_NONE);
7516
7517 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7518 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
7519 window->consumeKeyUp(ADISPLAY_ID_NONE);
7520
7521 spy->assertNoEvents();
7522}
7523
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00007524using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
7525
7526/**
7527 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
7528 * are currently sent to any other windows - including other spy windows - will also be cancelled.
7529 */
7530TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
7531 auto window = createForeground();
7532 auto spy1 = createSpy();
7533 auto spy2 = createSpy();
7534 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
7535
7536 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7537 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7538 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7539 window->consumeMotionDown();
7540 spy1->consumeMotionDown();
7541 spy2->consumeMotionDown();
7542
7543 // Pilfer pointers from the second spy window.
7544 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
7545 spy2->assertNoEvents();
7546 spy1->consumeMotionCancel();
7547 window->consumeMotionCancel();
7548
7549 // The rest of the gesture should only be sent to the second spy window.
7550 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7551 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7552 ADISPLAY_ID_DEFAULT))
7553 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7554 spy2->consumeMotionMove();
7555 spy1->assertNoEvents();
7556 window->assertNoEvents();
7557}
7558
7559/**
7560 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
7561 * in the middle of the gesture.
7562 */
7563TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
7564 auto window = createForeground();
7565 auto spy = createSpy();
7566 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7567
7568 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7569 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7570 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7571 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7572 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7573
7574 window->releaseChannel();
7575
7576 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
7577
7578 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7579 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7580 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7581 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7582}
7583
7584/**
7585 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
7586 * the spy, but not to any other windows.
7587 */
7588TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
7589 auto spy = createSpy();
7590 auto window = createForeground();
7591
7592 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7593
7594 // First finger down on the window and the spy.
7595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7596 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7597 {100, 200}))
7598 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7599 spy->consumeMotionDown();
7600 window->consumeMotionDown();
7601
7602 // Spy window pilfers the pointers.
7603 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
7604 window->consumeMotionCancel();
7605
7606 // Second finger down on the window and spy, but the window should not receive the pointer down.
7607 const MotionEvent secondFingerDownEvent =
7608 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7609 .displayId(ADISPLAY_ID_DEFAULT)
7610 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7611 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
7612 .x(100)
7613 .y(200))
7614 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7615 .build();
7616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7617 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7618 InputEventInjectionSync::WAIT_FOR_RESULT))
7619 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7620
7621 spy->consumeMotionPointerDown(1 /*pointerIndex*/);
7622
7623 // Third finger goes down outside all windows, so injection should fail.
7624 const MotionEvent thirdFingerDownEvent =
7625 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7626 .displayId(ADISPLAY_ID_DEFAULT)
7627 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7628 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
7629 .x(100)
7630 .y(200))
7631 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7632 .pointer(PointerBuilder(/* id */ 2, AMOTION_EVENT_TOOL_TYPE_FINGER).x(-5).y(-5))
7633 .build();
7634 ASSERT_EQ(InputEventInjectionResult::FAILED,
7635 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
7636 InputEventInjectionSync::WAIT_FOR_RESULT))
7637 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7638
7639 spy->assertNoEvents();
7640 window->assertNoEvents();
7641}
7642
7643/**
7644 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
7645 */
7646TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
7647 auto spy = createSpy();
7648 spy->setFrame(Rect(0, 0, 100, 100));
7649 auto window = createForeground();
7650 window->setFrame(Rect(0, 0, 200, 200));
7651
7652 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7653
7654 // First finger down on the window only
7655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7656 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7657 {150, 150}))
7658 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7659 window->consumeMotionDown();
7660
7661 // Second finger down on the spy and window
7662 const MotionEvent secondFingerDownEvent =
7663 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7664 .displayId(ADISPLAY_ID_DEFAULT)
7665 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7666 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
7667 .x(150)
7668 .y(150))
7669 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
7670 .build();
7671 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7672 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7673 InputEventInjectionSync::WAIT_FOR_RESULT))
7674 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7675 spy->consumeMotionDown();
7676 window->consumeMotionPointerDown(1);
7677
7678 // Third finger down on the spy and window
7679 const MotionEvent thirdFingerDownEvent =
7680 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7681 .displayId(ADISPLAY_ID_DEFAULT)
7682 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7683 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
7684 .x(150)
7685 .y(150))
7686 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
7687 .pointer(PointerBuilder(/* id */ 2, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7688 .build();
7689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7690 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
7691 InputEventInjectionSync::WAIT_FOR_RESULT))
7692 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7693 spy->consumeMotionPointerDown(1);
7694 window->consumeMotionPointerDown(2);
7695
7696 // Spy window pilfers the pointers.
7697 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
7698 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
7699 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
7700
7701 spy->assertNoEvents();
7702 window->assertNoEvents();
7703}
7704
7705/**
7706 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
7707 * other windows should be canceled. If this results in the cancellation of all pointers for some
7708 * window, then that window should receive ACTION_CANCEL.
7709 */
7710TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
7711 auto spy = createSpy();
7712 spy->setFrame(Rect(0, 0, 100, 100));
7713 auto window = createForeground();
7714 window->setFrame(Rect(0, 0, 200, 200));
7715
7716 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7717
7718 // First finger down on both spy and window
7719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7720 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7721 {10, 10}))
7722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7723 window->consumeMotionDown();
7724 spy->consumeMotionDown();
7725
7726 // Second finger down on the spy and window
7727 const MotionEvent secondFingerDownEvent =
7728 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7729 .displayId(ADISPLAY_ID_DEFAULT)
7730 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7731 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
7732 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7733 .build();
7734 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7735 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7736 InputEventInjectionSync::WAIT_FOR_RESULT))
7737 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7738 spy->consumeMotionPointerDown(1);
7739 window->consumeMotionPointerDown(1);
7740
7741 // Spy window pilfers the pointers.
7742 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
7743 window->consumeMotionCancel();
7744
7745 spy->assertNoEvents();
7746 window->assertNoEvents();
7747}
7748
7749/**
7750 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
7751 * be sent to other windows
7752 */
7753TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
7754 auto spy = createSpy();
7755 spy->setFrame(Rect(0, 0, 100, 100));
7756 auto window = createForeground();
7757 window->setFrame(Rect(0, 0, 200, 200));
7758
7759 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7760
7761 // First finger down on both window and spy
7762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7763 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7764 {10, 10}))
7765 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7766 window->consumeMotionDown();
7767 spy->consumeMotionDown();
7768
7769 // Spy window pilfers the pointers.
7770 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
7771 window->consumeMotionCancel();
7772
7773 // Second finger down on the window only
7774 const MotionEvent secondFingerDownEvent =
7775 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7776 .displayId(ADISPLAY_ID_DEFAULT)
7777 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7778 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
7779 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
7780 .x(150)
7781 .y(150))
7782 .build();
7783 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7784 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7785 InputEventInjectionSync::WAIT_FOR_RESULT))
7786 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7787 window->consumeMotionDown();
7788 window->assertNoEvents();
7789
7790 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
7791 spy->consumeMotionMove();
7792 spy->assertNoEvents();
7793}
7794
Prabir Pradhand65552b2021-10-07 11:23:50 -07007795class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
7796public:
7797 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
7798 std::shared_ptr<FakeApplicationHandle> overlayApplication =
7799 std::make_shared<FakeApplicationHandle>();
7800 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007801 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
7802 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07007803 overlay->setFocusable(false);
7804 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007805 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007806 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07007807 overlay->setTrustedOverlay(true);
7808
7809 std::shared_ptr<FakeApplicationHandle> application =
7810 std::make_shared<FakeApplicationHandle>();
7811 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007812 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
7813 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07007814 window->setFocusable(true);
7815 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07007816
7817 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7818 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
7819 setFocusedWindow(window);
7820 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
7821 return {std::move(overlay), std::move(window)};
7822 }
7823
7824 void sendFingerEvent(int32_t action) {
7825 NotifyMotionArgs motionArgs =
7826 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
7827 ADISPLAY_ID_DEFAULT, {PointF{20, 20}});
7828 mDispatcher->notifyMotion(&motionArgs);
7829 }
7830
7831 void sendStylusEvent(int32_t action) {
7832 NotifyMotionArgs motionArgs =
7833 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
7834 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
7835 motionArgs.pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
7836 mDispatcher->notifyMotion(&motionArgs);
7837 }
7838};
7839
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08007840using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
7841
7842TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
7843 ScopedSilentDeath _silentDeath;
7844
Prabir Pradhand65552b2021-10-07 11:23:50 -07007845 auto [overlay, window] = setupStylusOverlayScenario();
7846 overlay->setTrustedOverlay(false);
7847 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
7848 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
7849 ".* not a trusted overlay");
7850}
7851
7852TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
7853 auto [overlay, window] = setupStylusOverlayScenario();
7854 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
7855
7856 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
7857 overlay->consumeMotionDown();
7858 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
7859 overlay->consumeMotionUp();
7860
7861 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
7862 window->consumeMotionDown();
7863 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
7864 window->consumeMotionUp();
7865
7866 overlay->assertNoEvents();
7867 window->assertNoEvents();
7868}
7869
7870TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
7871 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007872 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07007873 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
7874
7875 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
7876 overlay->consumeMotionDown();
7877 window->consumeMotionDown();
7878 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
7879 overlay->consumeMotionUp();
7880 window->consumeMotionUp();
7881
7882 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
7883 window->consumeMotionDown();
7884 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
7885 window->consumeMotionUp();
7886
7887 overlay->assertNoEvents();
7888 window->assertNoEvents();
7889}
7890
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00007891/**
7892 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
7893 * The scenario is as follows:
7894 * - The stylus interceptor overlay is configured as a spy window.
7895 * - The stylus interceptor spy receives the start of a new stylus gesture.
7896 * - It pilfers pointers and then configures itself to no longer be a spy.
7897 * - The stylus interceptor continues to receive the rest of the gesture.
7898 */
7899TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
7900 auto [overlay, window] = setupStylusOverlayScenario();
7901 overlay->setSpy(true);
7902 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
7903
7904 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
7905 overlay->consumeMotionDown();
7906 window->consumeMotionDown();
7907
7908 // The interceptor pilfers the pointers.
7909 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
7910 window->consumeMotionCancel();
7911
7912 // The interceptor configures itself so that it is no longer a spy.
7913 overlay->setSpy(false);
7914 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
7915
7916 // It continues to receive the rest of the stylus gesture.
7917 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
7918 overlay->consumeMotionMove();
7919 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
7920 overlay->consumeMotionUp();
7921
7922 window->assertNoEvents();
7923}
7924
Prabir Pradhan5735a322022-04-11 17:23:34 +00007925struct User {
7926 int32_t mPid;
7927 int32_t mUid;
7928 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
7929 std::unique_ptr<InputDispatcher>& mDispatcher;
7930
7931 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
7932 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
7933
7934 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
7935 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
7936 ADISPLAY_ID_DEFAULT, {100, 200},
7937 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7938 AMOTION_EVENT_INVALID_CURSOR_POSITION},
7939 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
7940 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
7941 }
7942
7943 InputEventInjectionResult injectTargetedKey(int32_t action) const {
7944 return inputdispatcher::injectKey(mDispatcher, action, 0 /* repeatCount*/, ADISPLAY_ID_NONE,
7945 InputEventInjectionSync::WAIT_FOR_RESULT,
7946 INJECT_EVENT_TIMEOUT, false /*allowKeyRepeat*/, {mUid},
7947 mPolicyFlags);
7948 }
7949
7950 sp<FakeWindowHandle> createWindow() const {
7951 std::shared_ptr<FakeApplicationHandle> overlayApplication =
7952 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007953 sp<FakeWindowHandle> window =
7954 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
7955 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00007956 window->setOwnerInfo(mPid, mUid);
7957 return window;
7958 }
7959};
7960
7961using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
7962
7963TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
7964 auto owner = User(mDispatcher, 10, 11);
7965 auto window = owner.createWindow();
7966 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
7967
7968 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
7969 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
7970 window->consumeMotionDown();
7971
7972 setFocusedWindow(window);
7973 window->consumeFocusEvent(true);
7974
7975 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
7976 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
7977 window->consumeKeyDown(ADISPLAY_ID_NONE);
7978}
7979
7980TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
7981 auto owner = User(mDispatcher, 10, 11);
7982 auto window = owner.createWindow();
7983 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
7984
7985 auto rando = User(mDispatcher, 20, 21);
7986 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
7987 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
7988
7989 setFocusedWindow(window);
7990 window->consumeFocusEvent(true);
7991
7992 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
7993 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
7994 window->assertNoEvents();
7995}
7996
7997TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
7998 auto owner = User(mDispatcher, 10, 11);
7999 auto window = owner.createWindow();
8000 auto spy = owner.createWindow();
8001 spy->setSpy(true);
8002 spy->setTrustedOverlay(true);
8003 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8004
8005 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
8006 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
8007 spy->consumeMotionDown();
8008 window->consumeMotionDown();
8009}
8010
8011TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
8012 auto owner = User(mDispatcher, 10, 11);
8013 auto window = owner.createWindow();
8014
8015 auto rando = User(mDispatcher, 20, 21);
8016 auto randosSpy = rando.createWindow();
8017 randosSpy->setSpy(true);
8018 randosSpy->setTrustedOverlay(true);
8019 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
8020
8021 // The event is targeted at owner's window, so injection should succeed, but the spy should
8022 // not receive the event.
8023 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
8024 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
8025 randosSpy->assertNoEvents();
8026 window->consumeMotionDown();
8027}
8028
8029TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
8030 auto owner = User(mDispatcher, 10, 11);
8031 auto window = owner.createWindow();
8032
8033 auto rando = User(mDispatcher, 20, 21);
8034 auto randosSpy = rando.createWindow();
8035 randosSpy->setSpy(true);
8036 randosSpy->setTrustedOverlay(true);
8037 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
8038
8039 // A user that has injection permission can inject into any window.
8040 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
8041 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8042 ADISPLAY_ID_DEFAULT));
8043 randosSpy->consumeMotionDown();
8044 window->consumeMotionDown();
8045
8046 setFocusedWindow(randosSpy);
8047 randosSpy->consumeFocusEvent(true);
8048
8049 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
8050 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
8051 window->assertNoEvents();
8052}
8053
8054TEST_F(InputDispatcherTargetedInjectionTest, CanGenerateActionOutsideToOtherUids) {
8055 auto owner = User(mDispatcher, 10, 11);
8056 auto window = owner.createWindow();
8057
8058 auto rando = User(mDispatcher, 20, 21);
8059 auto randosWindow = rando.createWindow();
8060 randosWindow->setFrame(Rect{-10, -10, -5, -5});
8061 randosWindow->setWatchOutsideTouch(true);
8062 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
8063
8064 // We allow generation of ACTION_OUTSIDE events into windows owned by different uids.
8065 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
8066 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
8067 window->consumeMotionDown();
8068 randosWindow->consumeMotionOutside();
8069}
8070
Garfield Tane84e6f92019-08-29 17:28:41 -07008071} // namespace android::inputdispatcher