blob: 4341b0aa7e9db6ef27ee02210cb3113ced334f9d [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 Vishniakou487c49b2022-12-02 15:48:57 -080032#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070033#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080034#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080035#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080036
Garfield Tan1c7bc862020-01-28 13:24:04 -080037using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050038using android::gui::FocusRequest;
39using android::gui::TouchOcclusionMode;
40using android::gui::WindowInfo;
41using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080042using android::os::InputEventInjectionResult;
43using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080044
Garfield Tane84e6f92019-08-29 17:28:41 -070045namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080046
Dominik Laskowski2f01d772022-03-23 16:01:29 -070047using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080048using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070049
Michael Wrightd02c5b62014-02-10 15:10:22 -080050// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000051static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080052
53// An arbitrary device id.
Prabir Pradhan5735a322022-04-11 17:23:34 +000054static constexpr int32_t DEVICE_ID = 1;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080055static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080056
Jeff Brownf086ddb2014-02-11 14:28:48 -080057// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000058static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
59static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080060
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080061static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
62static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
63static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
64static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
65static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080066static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080067static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080068/**
69 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
70 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
71 * index 0) is the new pointer going down. The same pointer could have been placed at a different
72 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
73 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
74 * pointer id=0 leaves but the pointer id=1 remains.
75 */
76static constexpr int32_t POINTER_0_DOWN =
77 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080078static constexpr int32_t POINTER_1_DOWN =
79 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000080static constexpr int32_t POINTER_2_DOWN =
81 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000082static constexpr int32_t POINTER_3_DOWN =
83 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000084static constexpr int32_t POINTER_0_UP =
85 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080086static constexpr int32_t POINTER_1_UP =
87 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
88
Antonio Kantek15beb512022-06-13 22:35:41 +000089// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhan5735a322022-04-11 17:23:34 +000090static constexpr int32_t WINDOW_PID = 999;
91static constexpr int32_t WINDOW_UID = 1001;
92
Antonio Kantek15beb512022-06-13 22:35:41 +000093// The default pid and uid for the windows created on the secondary display by the test.
94static constexpr int32_t SECONDARY_WINDOW_PID = 1010;
95static constexpr int32_t SECONDARY_WINDOW_UID = 1012;
96
Prabir Pradhan5735a322022-04-11 17:23:34 +000097// The default policy flags to use for event injection by tests.
98static constexpr uint32_t DEFAULT_POLICY_FLAGS = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
Michael Wrightd02c5b62014-02-10 15:10:22 -080099
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000100// An arbitrary pid of the gesture monitor window
101static constexpr int32_t MONITOR_PID = 2001;
102
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800103static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
104
Arthur Hungc539dbb2022-12-08 07:45:36 +0000105static constexpr int expectedWallpaperFlags =
106 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
107
chaviwd1c23182019-12-20 18:44:56 -0800108struct PointF {
109 float x;
110 float y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800111 auto operator<=>(const PointF&) const = default;
chaviwd1c23182019-12-20 18:44:56 -0800112};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800113
Gang Wang342c9272020-01-13 13:15:04 -0500114/**
115 * Return a DOWN key event with KEYCODE_A.
116 */
117static KeyEvent getTestKeyEvent() {
118 KeyEvent event;
119
Garfield Tanfbe732e2020-01-24 11:26:14 -0800120 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
121 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
122 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500123 return event;
124}
125
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000126static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
127 ASSERT_EQ(expectedAction, receivedAction)
128 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
129 << MotionEvent::actionToString(receivedAction);
130}
131
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800132MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") {
133 bool matches = action == arg.getAction();
134 if (!matches) {
135 *result_listener << "expected action " << MotionEvent::actionToString(action)
136 << ", but got " << MotionEvent::actionToString(arg.getAction());
137 }
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800138 if (action == AMOTION_EVENT_ACTION_DOWN) {
139 if (!matches) {
140 *result_listener << "; ";
141 }
142 *result_listener << "downTime should match eventTime for ACTION_DOWN events";
143 matches &= arg.getDownTime() == arg.getEventTime();
144 }
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800145 if (action == AMOTION_EVENT_ACTION_CANCEL) {
146 if (!matches) {
147 *result_listener << "; ";
148 }
149 *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set";
150 matches &= (arg.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
151 }
152 return matches;
153}
154
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800155MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
156 return arg.getDownTime() == downTime;
157}
158
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800159MATCHER_P(WithDisplayId, displayId, "InputEvent with specified displayId") {
160 return arg.getDisplayId() == displayId;
161}
162
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800163MATCHER_P(WithDeviceId, deviceId, "InputEvent with specified deviceId") {
164 return arg.getDeviceId() == deviceId;
165}
166
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800167MATCHER_P(WithSource, source, "InputEvent with specified source") {
168 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
169 << inputEventSourceToString(arg.getSource());
170 return arg.getSource() == source;
171}
172
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800173MATCHER_P(WithFlags, flags, "InputEvent with specified flags") {
174 return arg.getFlags() == flags;
175}
176
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800177MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
178 if (arg.getPointerCount() != 1) {
179 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
180 return false;
181 }
Harry Cutts33476232023-01-30 19:57:29 +0000182 return arg.getX(/*pointerIndex=*/0) == x && arg.getY(/*pointerIndex=*/0) == y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800183}
184
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800185MATCHER_P(WithPointerCount, pointerCount, "MotionEvent with specified number of pointers") {
186 return arg.getPointerCount() == pointerCount;
187}
188
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800189MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
190 // Build a map for the received pointers, by pointer id
191 std::map<int32_t /*pointerId*/, PointF> actualPointers;
192 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
193 const int32_t pointerId = arg.getPointerId(pointerIndex);
194 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
195 }
196 return pointers == actualPointers;
197}
198
Michael Wrightd02c5b62014-02-10 15:10:22 -0800199// --- FakeInputDispatcherPolicy ---
200
201class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
202 InputDispatcherConfiguration mConfig;
203
Prabir Pradhanedd96402022-02-15 01:46:16 -0800204 using AnrResult = std::pair<sp<IBinder>, int32_t /*pid*/>;
205
Michael Wrightd02c5b62014-02-10 15:10:22 -0800206protected:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000207 virtual ~FakeInputDispatcherPolicy() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800208
209public:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000210 FakeInputDispatcherPolicy() {}
Jackal Guof9696682018-10-05 12:23:23 +0800211
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800212 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700213 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
214 ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_KEY);
215 EXPECT_EQ(event.getDisplayId(), args.displayId);
216
217 const auto& keyEvent = static_cast<const KeyEvent&>(event);
218 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
219 EXPECT_EQ(keyEvent.getAction(), args.action);
220 });
Jackal Guof9696682018-10-05 12:23:23 +0800221 }
222
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700223 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
224 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
225 ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_MOTION);
226 EXPECT_EQ(event.getDisplayId(), args.displayId);
227
228 const auto& motionEvent = static_cast<const MotionEvent&>(event);
229 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
230 EXPECT_EQ(motionEvent.getAction(), args.action);
231 EXPECT_EQ(motionEvent.getX(0), point.x);
232 EXPECT_EQ(motionEvent.getY(0), point.y);
233 EXPECT_EQ(motionEvent.getRawX(0), point.x);
234 EXPECT_EQ(motionEvent.getRawY(0), point.y);
235 });
Jackal Guof9696682018-10-05 12:23:23 +0800236 }
237
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700238 void assertFilterInputEventWasNotCalled() {
239 std::scoped_lock lock(mLock);
240 ASSERT_EQ(nullptr, mFilteredEvent);
241 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800242
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800243 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700244 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800245 ASSERT_TRUE(mConfigurationChangedTime)
246 << "Timed out waiting for configuration changed call";
247 ASSERT_EQ(*mConfigurationChangedTime, when);
248 mConfigurationChangedTime = std::nullopt;
249 }
250
251 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700252 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800253 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800254 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800255 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
256 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
257 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
258 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
259 mLastNotifySwitch = std::nullopt;
260 }
261
chaviwfd6d3512019-03-25 13:23:49 -0700262 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700263 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800264 ASSERT_EQ(touchedToken, mOnPointerDownToken);
265 mOnPointerDownToken.clear();
266 }
267
268 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700269 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800270 ASSERT_TRUE(mOnPointerDownToken == nullptr)
271 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700272 }
273
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700274 // This function must be called soon after the expected ANR timer starts,
275 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500276 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700277 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500278 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800279 std::unique_lock lock(mLock);
280 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500281 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800282 ASSERT_NO_FATAL_FAILURE(
283 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500284 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700285 }
286
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000287 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800288 const sp<WindowInfoHandle>& window) {
289 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
290 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
291 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500292 }
293
Prabir Pradhanedd96402022-02-15 01:46:16 -0800294 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
295 const sp<IBinder>& expectedToken,
296 int32_t expectedPid) {
297 std::unique_lock lock(mLock);
298 android::base::ScopedLockAssertion assumeLocked(mLock);
299 AnrResult result;
300 ASSERT_NO_FATAL_FAILURE(result =
301 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
302 const auto& [token, pid] = result;
303 ASSERT_EQ(expectedToken, token);
304 ASSERT_EQ(expectedPid, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500305 }
306
Prabir Pradhanedd96402022-02-15 01:46:16 -0800307 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000308 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500309 std::unique_lock lock(mLock);
310 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800311 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
312 const auto& [token, _] = result;
313 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000314 }
315
Prabir Pradhanedd96402022-02-15 01:46:16 -0800316 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
317 int32_t expectedPid) {
318 std::unique_lock lock(mLock);
319 android::base::ScopedLockAssertion assumeLocked(mLock);
320 AnrResult result;
321 ASSERT_NO_FATAL_FAILURE(
322 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
323 const auto& [token, pid] = result;
324 ASSERT_EQ(expectedToken, token);
325 ASSERT_EQ(expectedPid, pid);
326 }
327
328 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000329 sp<IBinder> getResponsiveWindowToken() {
330 std::unique_lock lock(mLock);
331 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800332 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
333 const auto& [token, _] = result;
334 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700335 }
336
337 void assertNotifyAnrWasNotCalled() {
338 std::scoped_lock lock(mLock);
339 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800340 ASSERT_TRUE(mAnrWindows.empty());
341 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500342 << "ANR was not called, but please also consume the 'connection is responsive' "
343 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700344 }
345
Garfield Tan1c7bc862020-01-28 13:24:04 -0800346 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
347 mConfig.keyRepeatTimeout = timeout;
348 mConfig.keyRepeatDelay = delay;
349 }
350
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000351 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800352 std::unique_lock lock(mLock);
353 base::ScopedLockAssertion assumeLocked(mLock);
354
355 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
356 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000357 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800358 enabled;
359 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000360 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
361 << ") to be called.";
362 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800363 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000364 auto request = *mPointerCaptureRequest;
365 mPointerCaptureRequest.reset();
366 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800367 }
368
369 void assertSetPointerCaptureNotCalled() {
370 std::unique_lock lock(mLock);
371 base::ScopedLockAssertion assumeLocked(mLock);
372
373 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000374 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800375 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000376 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800377 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000378 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800379 }
380
arthurhungf452d0b2021-01-06 00:19:52 +0800381 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
382 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800383 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800384 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800385 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800386 }
387
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800388 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
389 std::unique_lock lock(mLock);
390 base::ScopedLockAssertion assumeLocked(mLock);
391 std::optional<sp<IBinder>> receivedToken =
392 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
393 mNotifyInputChannelBroken);
394 ASSERT_TRUE(receivedToken.has_value());
395 ASSERT_EQ(token, *receivedToken);
396 }
397
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800398 /**
399 * Set policy timeout. A value of zero means next key will not be intercepted.
400 */
401 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
402 mInterceptKeyTimeout = timeout;
403 }
404
Michael Wrightd02c5b62014-02-10 15:10:22 -0800405private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700406 std::mutex mLock;
407 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
408 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
409 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
410 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800411
Prabir Pradhan99987712020-11-10 18:43:05 -0800412 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000413
414 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800415
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700416 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700417 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800418 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
419 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700420 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800421 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
422 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700423
arthurhungf452d0b2021-01-06 00:19:52 +0800424 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800425 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800426
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800427 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
428
Prabir Pradhanedd96402022-02-15 01:46:16 -0800429 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
430 // for a specific container to become non-empty. When the container is non-empty, return the
431 // first entry from the container and erase it.
432 template <class T>
433 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
434 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
435 // If there is an ANR, Dispatcher won't be idle because there are still events
436 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
437 // before checking if ANR was called.
438 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
439 // to provide it some time to act. 100ms seems reasonable.
440 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
441 const std::chrono::time_point start = std::chrono::steady_clock::now();
442 std::optional<T> token =
443 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
444 if (!token.has_value()) {
445 ADD_FAILURE() << "Did not receive the ANR callback";
446 return {};
447 }
448
449 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
450 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
451 // the dispatcher started counting before this function was called
452 if (std::chrono::abs(timeout - waited) > 100ms) {
453 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
454 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
455 << "ms, but waited "
456 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
457 << "ms instead";
458 }
459 return *token;
460 }
461
462 template <class T>
463 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
464 std::queue<T>& storage,
465 std::unique_lock<std::mutex>& lock,
466 std::condition_variable& condition)
467 REQUIRES(mLock) {
468 condition.wait_for(lock, timeout,
469 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
470 if (storage.empty()) {
471 ADD_FAILURE() << "Did not receive the expected callback";
472 return std::nullopt;
473 }
474 T item = storage.front();
475 storage.pop();
476 return std::make_optional(item);
477 }
478
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600479 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700480 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800481 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800482 }
483
Prabir Pradhanedd96402022-02-15 01:46:16 -0800484 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
485 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700486 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800487 ASSERT_TRUE(pid.has_value());
488 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700489 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500490 }
491
Prabir Pradhanedd96402022-02-15 01:46:16 -0800492 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
493 std::optional<int32_t> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500494 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800495 ASSERT_TRUE(pid.has_value());
496 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500497 mNotifyAnr.notify_all();
498 }
499
500 void notifyNoFocusedWindowAnr(
501 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
502 std::scoped_lock lock(mLock);
503 mAnrApplications.push(applicationHandle);
504 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800505 }
506
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800507 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
508 std::scoped_lock lock(mLock);
509 mBrokenInputChannels.push(connectionToken);
510 mNotifyInputChannelBroken.notify_all();
511 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800512
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600513 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700514
Chris Yef59a2f42020-10-16 12:55:26 -0700515 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
516 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
517 const std::vector<float>& values) override {}
518
519 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
520 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000521
Chris Yefb552902021-02-03 17:18:37 -0800522 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
523
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600524 void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800525 *outConfig = mConfig;
526 }
527
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600528 bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700529 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800530 switch (inputEvent->getType()) {
531 case AINPUT_EVENT_TYPE_KEY: {
532 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800533 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800534 break;
535 }
536
537 case AINPUT_EVENT_TYPE_MOTION: {
538 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800539 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800540 break;
541 }
542 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800543 return true;
544 }
545
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800546 void interceptKeyBeforeQueueing(const KeyEvent* inputEvent, uint32_t&) override {
547 if (inputEvent->getAction() == AKEY_EVENT_ACTION_UP) {
548 // Clear intercept state when we handled the event.
549 mInterceptKeyTimeout = 0ms;
550 }
551 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800552
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600553 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800554
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600555 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800556 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
557 // Clear intercept state so we could dispatch the event in next wake.
558 mInterceptKeyTimeout = 0ms;
559 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800560 }
561
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600562 bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800563 return false;
564 }
565
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600566 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
567 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700568 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800569 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
570 * essentially a passthrough for notifySwitch.
571 */
Harry Cutts33476232023-01-30 19:57:29 +0000572 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800573 }
574
Sean Stoutb4e0a592021-02-23 07:34:53 -0800575 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800576
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600577 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700578 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700579 mOnPointerDownToken = newToken;
580 }
581
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000582 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800583 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000584 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800585 mPointerCaptureChangedCondition.notify_all();
586 }
587
arthurhungf452d0b2021-01-06 00:19:52 +0800588 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
589 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800590 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800591 mDropTargetWindowToken = token;
592 }
593
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700594 void assertFilterInputEventWasCalledInternal(
595 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700596 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800597 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700598 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800599 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800600 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800601};
602
Michael Wrightd02c5b62014-02-10 15:10:22 -0800603// --- InputDispatcherTest ---
604
605class InputDispatcherTest : public testing::Test {
606protected:
607 sp<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700608 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800609
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000610 void SetUp() override {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700611 mFakePolicy = sp<FakeInputDispatcherPolicy>::make();
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800612 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800613 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000614 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700615 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800616 }
617
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000618 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700619 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800620 mFakePolicy.clear();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700621 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800622 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700623
624 /**
625 * Used for debugging when writing the test
626 */
627 void dumpDispatcherState() {
628 std::string dump;
629 mDispatcher->dump(dump);
630 std::stringstream ss(dump);
631 std::string to;
632
633 while (std::getline(ss, to, '\n')) {
634 ALOGE("%s", to.c_str());
635 }
636 }
Vishnu Nair958da932020-08-21 17:12:37 -0700637
chaviw3277faf2021-05-19 16:45:23 -0500638 void setFocusedWindow(const sp<WindowInfoHandle>& window,
639 const sp<WindowInfoHandle>& focusedWindow = nullptr) {
Vishnu Nair958da932020-08-21 17:12:37 -0700640 FocusRequest request;
641 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000642 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700643 if (focusedWindow) {
644 request.focusedToken = focusedWindow->getToken();
645 }
646 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
647 request.displayId = window->getInfo()->displayId;
648 mDispatcher->setFocusedWindow(request);
649 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800650};
651
Michael Wrightd02c5b62014-02-10 15:10:22 -0800652TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
653 KeyEvent event;
654
655 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800656 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
657 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600658 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
659 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800660 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000661 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000662 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800663 << "Should reject key events with undefined action.";
664
665 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800666 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
667 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600668 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800669 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000670 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000671 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800672 << "Should reject key events with ACTION_MULTIPLE.";
673}
674
675TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
676 MotionEvent event;
677 PointerProperties pointerProperties[MAX_POINTERS + 1];
678 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800679 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800680 pointerProperties[i].clear();
681 pointerProperties[i].id = i;
682 pointerCoords[i].clear();
683 }
684
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800685 // Some constants commonly used below
686 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
687 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
688 constexpr int32_t metaState = AMETA_NONE;
689 constexpr MotionClassification classification = MotionClassification::NONE;
690
chaviw9eaa22c2020-07-01 16:21:27 -0700691 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800692 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800693 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700694 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
695 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700696 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
697 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700698 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800699 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000700 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000701 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800702 << "Should reject motion events with undefined action.";
703
704 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800705 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800706 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
707 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
708 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
709 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500710 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800711 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000712 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000713 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800714 << "Should reject motion events with pointer down index too large.";
715
Garfield Tanfbe732e2020-01-24 11:26:14 -0800716 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700717 AMOTION_EVENT_ACTION_POINTER_DOWN |
718 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700719 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
720 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700721 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500722 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800723 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000724 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000725 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800726 << "Should reject motion events with pointer down index too small.";
727
728 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800729 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800730 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
731 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
732 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
733 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500734 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800735 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000736 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000737 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800738 << "Should reject motion events with pointer up index too large.";
739
Garfield Tanfbe732e2020-01-24 11:26:14 -0800740 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700741 AMOTION_EVENT_ACTION_POINTER_UP |
742 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700743 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
744 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700745 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500746 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800747 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000748 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000749 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800750 << "Should reject motion events with pointer up index too small.";
751
752 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800753 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
754 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700755 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700756 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
757 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700758 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800759 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000760 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000761 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800762 << "Should reject motion events with 0 pointers.";
763
Garfield Tanfbe732e2020-01-24 11:26:14 -0800764 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
765 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700766 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700767 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
768 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700769 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800770 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000771 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000772 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800773 << "Should reject motion events with more than MAX_POINTERS pointers.";
774
775 // Rejects motion events with invalid pointer ids.
776 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800777 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
778 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700779 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700780 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
781 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700782 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800783 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000784 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000785 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800786 << "Should reject motion events with pointer ids less than 0.";
787
788 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800789 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
790 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700791 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700792 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
793 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700794 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800795 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000796 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000797 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800798 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
799
800 // Rejects motion events with duplicate pointer ids.
801 pointerProperties[0].id = 1;
802 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800803 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
804 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700805 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700806 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
807 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700808 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800809 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000810 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000811 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800812 << "Should reject motion events with duplicate pointer ids.";
813}
814
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800815/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
816
817TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
818 constexpr nsecs_t eventTime = 20;
Harry Cutts33476232023-01-30 19:57:29 +0000819 NotifyConfigurationChangedArgs args(/*id=*/10, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800820 mDispatcher->notifyConfigurationChanged(&args);
821 ASSERT_TRUE(mDispatcher->waitForIdle());
822
823 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
824}
825
826TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000827 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
828 /*switchMask=*/2);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800829 mDispatcher->notifySwitch(&args);
830
831 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
832 args.policyFlags |= POLICY_FLAG_TRUSTED;
833 mFakePolicy->assertNotifySwitchWasCalled(args);
834}
835
Arthur Hungb92218b2018-08-14 12:00:21 +0800836// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700837static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700838// Default input dispatching timeout if there is no focused application or paused window
839// from which to determine an appropriate dispatching timeout.
840static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
841 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
842 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800843
844class FakeApplicationHandle : public InputApplicationHandle {
845public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700846 FakeApplicationHandle() {
847 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700848 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500849 mInfo.dispatchingTimeoutMillis =
850 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700851 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800852 virtual ~FakeApplicationHandle() {}
853
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000854 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700855
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500856 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
857 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700858 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800859};
860
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800861class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800862public:
Garfield Tan15601662020-09-22 15:32:38 -0700863 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800864 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700865 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800866 }
867
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800868 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700869 InputEvent* event;
870 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
871 if (!consumeSeq) {
872 return nullptr;
873 }
874 finishEvent(*consumeSeq);
875 return event;
876 }
877
878 /**
879 * Receive an event without acknowledging it.
880 * Return the sequence number that could later be used to send finished signal.
881 */
882 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800883 uint32_t consumeSeq;
884 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800885
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800886 std::chrono::time_point start = std::chrono::steady_clock::now();
887 status_t status = WOULD_BLOCK;
888 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000889 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800890 &event);
891 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
892 if (elapsed > 100ms) {
893 break;
894 }
895 }
896
897 if (status == WOULD_BLOCK) {
898 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700899 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800900 }
901
902 if (status != OK) {
903 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700904 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800905 }
906 if (event == nullptr) {
907 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700908 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800909 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700910 if (outEvent != nullptr) {
911 *outEvent = event;
912 }
913 return consumeSeq;
914 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800915
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700916 /**
917 * To be used together with "receiveEvent" to complete the consumption of an event.
918 */
919 void finishEvent(uint32_t consumeSeq) {
920 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
921 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800922 }
923
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000924 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
925 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
926 ASSERT_EQ(OK, status);
927 }
928
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000929 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
930 std::optional<int32_t> expectedDisplayId,
931 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800932 InputEvent* event = consume();
933
934 ASSERT_NE(nullptr, event) << mName.c_str()
935 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800936 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700937 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800938 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800939
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000940 if (expectedDisplayId.has_value()) {
941 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
942 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800943
Tiger Huang8664f8c2018-10-11 19:14:35 +0800944 switch (expectedEventType) {
945 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800946 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
947 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000948 if (expectedFlags.has_value()) {
949 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
950 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800951 break;
952 }
953 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800954 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000955 assertMotionAction(expectedAction, motionEvent.getAction());
956
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000957 if (expectedFlags.has_value()) {
958 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
959 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800960 break;
961 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100962 case AINPUT_EVENT_TYPE_FOCUS: {
963 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
964 }
Prabir Pradhan99987712020-11-10 18:43:05 -0800965 case AINPUT_EVENT_TYPE_CAPTURE: {
966 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
967 }
Antonio Kantekf16f2832021-09-28 04:39:20 +0000968 case AINPUT_EVENT_TYPE_TOUCH_MODE: {
969 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
970 }
arthurhungb89ccb02020-12-30 16:19:01 +0800971 case AINPUT_EVENT_TYPE_DRAG: {
972 FAIL() << "Use 'consumeDragEvent' for DRAG events";
973 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800974 default: {
975 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
976 }
977 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800978 }
979
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800980 MotionEvent* consumeMotion() {
981 InputEvent* event = consume();
982
983 if (event == nullptr) {
984 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
985 return nullptr;
986 }
987
988 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
989 ADD_FAILURE() << mName << " expected a MotionEvent, got "
990 << inputEventTypeToString(event->getType()) << " event";
991 return nullptr;
992 }
993 return static_cast<MotionEvent*>(event);
994 }
995
996 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
997 MotionEvent* motionEvent = consumeMotion();
998 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
999 ASSERT_THAT(*motionEvent, matcher);
1000 }
1001
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001002 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1003 InputEvent* event = consume();
1004 ASSERT_NE(nullptr, event) << mName.c_str()
1005 << ": consumer should have returned non-NULL event.";
1006 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
1007 << "Got " << inputEventTypeToString(event->getType())
1008 << " event instead of FOCUS event";
1009
1010 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1011 << mName.c_str() << ": event displayId should always be NONE.";
1012
1013 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1014 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001015 }
1016
Prabir Pradhan99987712020-11-10 18:43:05 -08001017 void consumeCaptureEvent(bool hasCapture) {
1018 const InputEvent* event = consume();
1019 ASSERT_NE(nullptr, event) << mName.c_str()
1020 << ": consumer should have returned non-NULL event.";
1021 ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType())
1022 << "Got " << inputEventTypeToString(event->getType())
1023 << " event instead of CAPTURE event";
1024
1025 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1026 << mName.c_str() << ": event displayId should always be NONE.";
1027
1028 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1029 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1030 }
1031
arthurhungb89ccb02020-12-30 16:19:01 +08001032 void consumeDragEvent(bool isExiting, float x, float y) {
1033 const InputEvent* event = consume();
1034 ASSERT_NE(nullptr, event) << mName.c_str()
1035 << ": consumer should have returned non-NULL event.";
1036 ASSERT_EQ(AINPUT_EVENT_TYPE_DRAG, event->getType())
1037 << "Got " << inputEventTypeToString(event->getType())
1038 << " event instead of DRAG event";
1039
1040 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1041 << mName.c_str() << ": event displayId should always be NONE.";
1042
1043 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1044 EXPECT_EQ(isExiting, dragEvent.isExiting());
1045 EXPECT_EQ(x, dragEvent.getX());
1046 EXPECT_EQ(y, dragEvent.getY());
1047 }
1048
Antonio Kantekf16f2832021-09-28 04:39:20 +00001049 void consumeTouchModeEvent(bool inTouchMode) {
1050 const InputEvent* event = consume();
1051 ASSERT_NE(nullptr, event) << mName.c_str()
1052 << ": consumer should have returned non-NULL event.";
1053 ASSERT_EQ(AINPUT_EVENT_TYPE_TOUCH_MODE, event->getType())
1054 << "Got " << inputEventTypeToString(event->getType())
1055 << " event instead of TOUCH_MODE event";
1056
1057 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1058 << mName.c_str() << ": event displayId should always be NONE.";
1059 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1060 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1061 }
1062
chaviwd1c23182019-12-20 18:44:56 -08001063 void assertNoEvents() {
1064 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001065 if (event == nullptr) {
1066 return;
1067 }
1068 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
1069 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1070 ADD_FAILURE() << "Received key event "
1071 << KeyEvent::actionToString(keyEvent.getAction());
1072 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
1073 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1074 ADD_FAILURE() << "Received motion event "
1075 << MotionEvent::actionToString(motionEvent.getAction());
1076 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
1077 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1078 ADD_FAILURE() << "Received focus event, hasFocus = "
1079 << (focusEvent.getHasFocus() ? "true" : "false");
Prabir Pradhan99987712020-11-10 18:43:05 -08001080 } else if (event->getType() == AINPUT_EVENT_TYPE_CAPTURE) {
1081 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1082 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1083 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Antonio Kantekf16f2832021-09-28 04:39:20 +00001084 } else if (event->getType() == AINPUT_EVENT_TYPE_TOUCH_MODE) {
1085 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1086 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1087 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001088 }
1089 FAIL() << mName.c_str()
1090 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001091 }
1092
1093 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1094
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001095 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1096
chaviwd1c23182019-12-20 18:44:56 -08001097protected:
1098 std::unique_ptr<InputConsumer> mConsumer;
1099 PreallocatedInputEventFactory mEventFactory;
1100
1101 std::string mName;
1102};
1103
chaviw3277faf2021-05-19 16:45:23 -05001104class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001105public:
1106 static const int32_t WIDTH = 600;
1107 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001108
Chris Yea209fde2020-07-22 13:54:51 -07001109 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001110 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001111 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001112 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001113 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001114 base::Result<std::unique_ptr<InputChannel>> channel =
1115 dispatcher->createInputChannel(name);
1116 token = (*channel)->getConnectionToken();
1117 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001118 }
1119
1120 inputApplicationHandle->updateInfo();
1121 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1122
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001123 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001124 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001125 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001126 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001127 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001128 mInfo.frameLeft = 0;
1129 mInfo.frameTop = 0;
1130 mInfo.frameRight = WIDTH;
1131 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001132 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001133 mInfo.globalScaleFactor = 1.0;
1134 mInfo.touchableRegion.clear();
1135 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001136 mInfo.ownerPid = WINDOW_PID;
1137 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001138 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001139 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001140 }
1141
Arthur Hungabbb9d82021-09-01 14:52:30 +00001142 sp<FakeWindowHandle> clone(
1143 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001144 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00001145 sp<FakeWindowHandle> handle =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001146 sp<FakeWindowHandle>::make(inputApplicationHandle, dispatcher,
1147 mInfo.name + "(Mirror)", displayId, mInfo.token);
Arthur Hungabbb9d82021-09-01 14:52:30 +00001148 return handle;
1149 }
1150
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001151 void setTouchable(bool touchable) {
1152 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1153 }
chaviwd1c23182019-12-20 18:44:56 -08001154
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001155 void setFocusable(bool focusable) {
1156 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1157 }
1158
1159 void setVisible(bool visible) {
1160 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1161 }
Vishnu Nair958da932020-08-21 17:12:37 -07001162
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001163 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001164 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001165 }
1166
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001167 void setPaused(bool paused) {
1168 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1169 }
1170
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001171 void setPreventSplitting(bool preventSplitting) {
1172 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001173 }
1174
1175 void setSlippery(bool slippery) {
1176 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1177 }
1178
1179 void setWatchOutsideTouch(bool watchOutside) {
1180 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1181 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001182
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001183 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1184
1185 void setInterceptsStylus(bool interceptsStylus) {
1186 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1187 }
1188
1189 void setDropInput(bool dropInput) {
1190 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1191 }
1192
1193 void setDropInputIfObscured(bool dropInputIfObscured) {
1194 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1195 }
1196
1197 void setNoInputChannel(bool noInputChannel) {
1198 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1199 }
1200
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001201 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1202
chaviw3277faf2021-05-19 16:45:23 -05001203 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001204
Bernardo Rufino7393d172021-02-26 13:56:11 +00001205 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1206
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001207 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001208 mInfo.frameLeft = frame.left;
1209 mInfo.frameTop = frame.top;
1210 mInfo.frameRight = frame.right;
1211 mInfo.frameBottom = frame.bottom;
1212 mInfo.touchableRegion.clear();
1213 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001214
1215 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1216 ui::Transform translate;
1217 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1218 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001219 }
1220
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001221 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1222
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001223 void setIsWallpaper(bool isWallpaper) {
1224 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1225 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001226
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001227 void setDupTouchToWallpaper(bool hasWallpaper) {
1228 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1229 }
chaviwd1c23182019-12-20 18:44:56 -08001230
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001231 void setTrustedOverlay(bool trustedOverlay) {
1232 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1233 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001234
chaviw9eaa22c2020-07-01 16:21:27 -07001235 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1236 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1237 }
1238
1239 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001240
yunho.shinf4a80b82020-11-16 21:13:57 +09001241 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1242
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001243 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1244 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1245 expectedFlags);
1246 }
1247
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001248 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1249 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
1250 }
1251
Svet Ganov5d3bc372020-01-26 23:11:07 -08001252 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001253 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001254 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1255 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001256 }
1257
1258 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001259 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001260 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1261 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001262 }
1263
1264 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001265 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001266 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1267 }
1268
1269 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1270 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001271 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
1272 expectedFlags);
1273 }
1274
Svet Ganov5d3bc372020-01-26 23:11:07 -08001275 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001276 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1277 int32_t expectedFlags = 0) {
1278 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1279 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001280 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1281 }
1282
1283 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001284 int32_t expectedFlags = 0) {
1285 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1286 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001287 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1288 }
1289
1290 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001291 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +00001292 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
1293 expectedFlags);
1294 }
1295
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001296 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1297 int32_t expectedFlags = 0) {
1298 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
1299 expectedFlags);
1300 }
1301
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001302 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1303 int32_t expectedFlags = 0) {
1304 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001305 ASSERT_NE(nullptr, event);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001306 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
1307 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1308 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1309 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1310 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1311 }
1312
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001313 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1314 ASSERT_NE(mInputReceiver, nullptr)
1315 << "Cannot consume events from a window with no receiver";
1316 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1317 }
1318
Prabir Pradhan99987712020-11-10 18:43:05 -08001319 void consumeCaptureEvent(bool hasCapture) {
1320 ASSERT_NE(mInputReceiver, nullptr)
1321 << "Cannot consume events from a window with no receiver";
1322 mInputReceiver->consumeCaptureEvent(hasCapture);
1323 }
1324
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001325 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1326 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001327 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001328 ASSERT_THAT(*motionEvent, matcher);
1329 }
1330
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001331 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
1332 std::optional<int32_t> expectedDisplayId,
1333 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001334 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1335 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1336 expectedFlags);
1337 }
1338
arthurhungb89ccb02020-12-30 16:19:01 +08001339 void consumeDragEvent(bool isExiting, float x, float y) {
1340 mInputReceiver->consumeDragEvent(isExiting, x, y);
1341 }
1342
Antonio Kantekf16f2832021-09-28 04:39:20 +00001343 void consumeTouchModeEvent(bool inTouchMode) {
1344 ASSERT_NE(mInputReceiver, nullptr)
1345 << "Cannot consume events from a window with no receiver";
1346 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1347 }
1348
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001349 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001350 if (mInputReceiver == nullptr) {
1351 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1352 return std::nullopt;
1353 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001354 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001355 }
1356
1357 void finishEvent(uint32_t sequenceNum) {
1358 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1359 mInputReceiver->finishEvent(sequenceNum);
1360 }
1361
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001362 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1363 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1364 mInputReceiver->sendTimeline(inputEventId, timeline);
1365 }
1366
chaviwaf87b3e2019-10-01 16:59:28 -07001367 InputEvent* consume() {
1368 if (mInputReceiver == nullptr) {
1369 return nullptr;
1370 }
1371 return mInputReceiver->consume();
1372 }
1373
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001374 MotionEvent* consumeMotion() {
1375 InputEvent* event = consume();
1376 if (event == nullptr) {
1377 ADD_FAILURE() << "Consume failed : no event";
1378 return nullptr;
1379 }
1380 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
1381 ADD_FAILURE() << "Instead of motion event, got "
1382 << inputEventTypeToString(event->getType());
1383 return nullptr;
1384 }
1385 return static_cast<MotionEvent*>(event);
1386 }
1387
Arthur Hungb92218b2018-08-14 12:00:21 +08001388 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001389 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001390 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001391 return; // Can't receive events if the window does not have input channel
1392 }
1393 ASSERT_NE(nullptr, mInputReceiver)
1394 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001395 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001396 }
1397
chaviwaf87b3e2019-10-01 16:59:28 -07001398 sp<IBinder> getToken() { return mInfo.token; }
1399
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001400 const std::string& getName() { return mName; }
1401
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001402 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1403 mInfo.ownerPid = ownerPid;
1404 mInfo.ownerUid = ownerUid;
1405 }
1406
Prabir Pradhanedd96402022-02-15 01:46:16 -08001407 int32_t getPid() const { return mInfo.ownerPid; }
1408
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001409 void destroyReceiver() { mInputReceiver = nullptr; }
1410
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001411 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1412
chaviwd1c23182019-12-20 18:44:56 -08001413private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001414 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001415 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001416 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001417};
1418
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001419std::atomic<int32_t> FakeWindowHandle::sId{1};
1420
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001421static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001422 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001423 int32_t displayId = ADISPLAY_ID_NONE,
1424 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001425 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001426 bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
1427 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001428 KeyEvent event;
1429 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1430
1431 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001432 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001433 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1434 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001435
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001436 if (!allowKeyRepeat) {
1437 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1438 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001439 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001440 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001441}
1442
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001443static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001444 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001445 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001446}
1447
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001448// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1449// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1450// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001451static InputEventInjectionResult injectKeyDownNoRepeat(
1452 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001453 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001454 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001455 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001456}
1457
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001458static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001459 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001460 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001461}
1462
Garfield Tandf26e862020-07-01 20:18:19 -07001463class PointerBuilder {
1464public:
1465 PointerBuilder(int32_t id, int32_t toolType) {
1466 mProperties.clear();
1467 mProperties.id = id;
1468 mProperties.toolType = toolType;
1469 mCoords.clear();
1470 }
1471
1472 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1473
1474 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1475
1476 PointerBuilder& axis(int32_t axis, float value) {
1477 mCoords.setAxisValue(axis, value);
1478 return *this;
1479 }
1480
1481 PointerProperties buildProperties() const { return mProperties; }
1482
1483 PointerCoords buildCoords() const { return mCoords; }
1484
1485private:
1486 PointerProperties mProperties;
1487 PointerCoords mCoords;
1488};
1489
1490class MotionEventBuilder {
1491public:
1492 MotionEventBuilder(int32_t action, int32_t source) {
1493 mAction = action;
1494 mSource = source;
1495 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001496 mDownTime = mEventTime;
Garfield Tandf26e862020-07-01 20:18:19 -07001497 }
1498
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001499 MotionEventBuilder& deviceId(int32_t deviceId) {
1500 mDeviceId = deviceId;
1501 return *this;
1502 }
1503
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001504 MotionEventBuilder& downTime(nsecs_t downTime) {
1505 mDownTime = downTime;
1506 return *this;
1507 }
1508
Garfield Tandf26e862020-07-01 20:18:19 -07001509 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1510 mEventTime = eventTime;
1511 return *this;
1512 }
1513
1514 MotionEventBuilder& displayId(int32_t displayId) {
1515 mDisplayId = displayId;
1516 return *this;
1517 }
1518
1519 MotionEventBuilder& actionButton(int32_t actionButton) {
1520 mActionButton = actionButton;
1521 return *this;
1522 }
1523
arthurhung6d4bed92021-03-17 11:59:33 +08001524 MotionEventBuilder& buttonState(int32_t buttonState) {
1525 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001526 return *this;
1527 }
1528
1529 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1530 mRawXCursorPosition = rawXCursorPosition;
1531 return *this;
1532 }
1533
1534 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1535 mRawYCursorPosition = rawYCursorPosition;
1536 return *this;
1537 }
1538
1539 MotionEventBuilder& pointer(PointerBuilder pointer) {
1540 mPointers.push_back(pointer);
1541 return *this;
1542 }
1543
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001544 MotionEventBuilder& addFlag(uint32_t flags) {
1545 mFlags |= flags;
1546 return *this;
1547 }
1548
Garfield Tandf26e862020-07-01 20:18:19 -07001549 MotionEvent build() {
1550 std::vector<PointerProperties> pointerProperties;
1551 std::vector<PointerCoords> pointerCoords;
1552 for (const PointerBuilder& pointer : mPointers) {
1553 pointerProperties.push_back(pointer.buildProperties());
1554 pointerCoords.push_back(pointer.buildCoords());
1555 }
1556
1557 // Set mouse cursor position for the most common cases to avoid boilerplate.
1558 if (mSource == AINPUT_SOURCE_MOUSE &&
1559 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1560 mPointers.size() == 1) {
1561 mRawXCursorPosition = pointerCoords[0].getX();
1562 mRawYCursorPosition = pointerCoords[0].getY();
1563 }
1564
1565 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001566 ui::Transform identityTransform;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001567 event.initialize(InputEvent::nextId(), mDeviceId, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001568 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001569 mButtonState, MotionClassification::NONE, identityTransform,
1570 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001571 mRawYCursorPosition, identityTransform, mDownTime, mEventTime,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07001572 mPointers.size(), pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001573
1574 return event;
1575 }
1576
1577private:
1578 int32_t mAction;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001579 int32_t mDeviceId = DEVICE_ID;
Garfield Tandf26e862020-07-01 20:18:19 -07001580 int32_t mSource;
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001581 nsecs_t mDownTime;
Garfield Tandf26e862020-07-01 20:18:19 -07001582 nsecs_t mEventTime;
1583 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1584 int32_t mActionButton{0};
1585 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001586 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001587 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1588 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1589
1590 std::vector<PointerBuilder> mPointers;
1591};
1592
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001593class MotionArgsBuilder {
1594public:
1595 MotionArgsBuilder(int32_t action, int32_t source) {
1596 mAction = action;
1597 mSource = source;
1598 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1599 mDownTime = mEventTime;
1600 }
1601
1602 MotionArgsBuilder& deviceId(int32_t deviceId) {
1603 mDeviceId = deviceId;
1604 return *this;
1605 }
1606
1607 MotionArgsBuilder& downTime(nsecs_t downTime) {
1608 mDownTime = downTime;
1609 return *this;
1610 }
1611
1612 MotionArgsBuilder& eventTime(nsecs_t eventTime) {
1613 mEventTime = eventTime;
1614 return *this;
1615 }
1616
1617 MotionArgsBuilder& displayId(int32_t displayId) {
1618 mDisplayId = displayId;
1619 return *this;
1620 }
1621
1622 MotionArgsBuilder& policyFlags(int32_t policyFlags) {
1623 mPolicyFlags = policyFlags;
1624 return *this;
1625 }
1626
1627 MotionArgsBuilder& actionButton(int32_t actionButton) {
1628 mActionButton = actionButton;
1629 return *this;
1630 }
1631
1632 MotionArgsBuilder& buttonState(int32_t buttonState) {
1633 mButtonState = buttonState;
1634 return *this;
1635 }
1636
1637 MotionArgsBuilder& rawXCursorPosition(float rawXCursorPosition) {
1638 mRawXCursorPosition = rawXCursorPosition;
1639 return *this;
1640 }
1641
1642 MotionArgsBuilder& rawYCursorPosition(float rawYCursorPosition) {
1643 mRawYCursorPosition = rawYCursorPosition;
1644 return *this;
1645 }
1646
1647 MotionArgsBuilder& pointer(PointerBuilder pointer) {
1648 mPointers.push_back(pointer);
1649 return *this;
1650 }
1651
1652 MotionArgsBuilder& addFlag(uint32_t flags) {
1653 mFlags |= flags;
1654 return *this;
1655 }
1656
1657 NotifyMotionArgs build() {
1658 std::vector<PointerProperties> pointerProperties;
1659 std::vector<PointerCoords> pointerCoords;
1660 for (const PointerBuilder& pointer : mPointers) {
1661 pointerProperties.push_back(pointer.buildProperties());
1662 pointerCoords.push_back(pointer.buildCoords());
1663 }
1664
1665 // Set mouse cursor position for the most common cases to avoid boilerplate.
1666 if (mSource == AINPUT_SOURCE_MOUSE &&
1667 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1668 mPointers.size() == 1) {
1669 mRawXCursorPosition = pointerCoords[0].getX();
1670 mRawYCursorPosition = pointerCoords[0].getY();
1671 }
1672
1673 NotifyMotionArgs args(InputEvent::nextId(), mEventTime, /*readTime=*/mEventTime, mDeviceId,
1674 mSource, mDisplayId, mPolicyFlags, mAction, mActionButton, mFlags,
1675 AMETA_NONE, mButtonState, MotionClassification::NONE, /*edgeFlags=*/0,
1676 mPointers.size(), pointerProperties.data(), pointerCoords.data(),
1677 /*xPrecision=*/0, /*yPrecision=*/0, mRawXCursorPosition,
1678 mRawYCursorPosition, mDownTime, /*videoFrames=*/{});
1679
1680 return args;
1681 }
1682
1683private:
1684 int32_t mAction;
1685 int32_t mDeviceId = DEVICE_ID;
1686 int32_t mSource;
1687 nsecs_t mDownTime;
1688 nsecs_t mEventTime;
1689 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1690 int32_t mPolicyFlags = DEFAULT_POLICY_FLAGS;
1691 int32_t mActionButton{0};
1692 int32_t mButtonState{0};
1693 int32_t mFlags{0};
1694 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1695 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1696
1697 std::vector<PointerBuilder> mPointers;
1698};
1699
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001700static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001701 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001702 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001703 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1704 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
1705 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1706 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001707}
1708
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001709static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001710 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001711 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001712 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001713 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1714 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001715 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001716 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
1717 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Garfield Tandf26e862020-07-01 20:18:19 -07001718 MotionEvent event = MotionEventBuilder(action, source)
1719 .displayId(displayId)
1720 .eventTime(eventTime)
1721 .rawXCursorPosition(cursorPosition.x)
1722 .rawYCursorPosition(cursorPosition.y)
Harry Cutts33476232023-01-30 19:57:29 +00001723 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER)
Garfield Tandf26e862020-07-01 20:18:19 -07001724 .x(position.x)
1725 .y(position.y))
1726 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001727
1728 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001729 return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode, targetUid,
1730 policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001731}
1732
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001733static InputEventInjectionResult injectMotionDown(
1734 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1735 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001736 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001737}
1738
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001739static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001740 int32_t source, int32_t displayId,
1741 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001742 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001743}
1744
Jackal Guof9696682018-10-05 12:23:23 +08001745static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1746 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1747 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001748 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001749 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1750 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001751
1752 return args;
1753}
1754
chaviwd1c23182019-12-20 18:44:56 -08001755static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1756 const std::vector<PointF>& points) {
1757 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001758 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1759 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1760 }
1761
chaviwd1c23182019-12-20 18:44:56 -08001762 PointerProperties pointerProperties[pointerCount];
1763 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001764
chaviwd1c23182019-12-20 18:44:56 -08001765 for (size_t i = 0; i < pointerCount; i++) {
1766 pointerProperties[i].clear();
1767 pointerProperties[i].id = i;
1768 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001769
chaviwd1c23182019-12-20 18:44:56 -08001770 pointerCoords[i].clear();
1771 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1772 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1773 }
Jackal Guof9696682018-10-05 12:23:23 +08001774
1775 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1776 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001777 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001778 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1779 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001780 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1781 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001782 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1783 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001784
1785 return args;
1786}
1787
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001788static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1789 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1790}
1791
chaviwd1c23182019-12-20 18:44:56 -08001792static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1793 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1794}
1795
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001796static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1797 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001798 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001799}
1800
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001801/**
1802 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1803 * broken channel.
1804 */
1805TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1806 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1807 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001808 sp<FakeWindowHandle>::make(application, mDispatcher,
1809 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001810
1811 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1812
1813 // Window closes its channel, but the window remains.
1814 window->destroyReceiver();
1815 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1816}
1817
Arthur Hungb92218b2018-08-14 12:00:21 +08001818TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001819 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001820 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1821 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001822
Arthur Hung72d8dc32020-03-28 00:48:39 +00001823 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1825 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1826 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001827
1828 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001829 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001830}
1831
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001832TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1833 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001834 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1835 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001836
1837 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1838 // Inject a MotionEvent to an unknown display.
1839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1840 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1841 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1842
1843 // Window should receive motion event.
1844 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1845}
1846
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001847/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001848 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001849 * This test serves as a sanity check for the next test, where setInputWindows is
1850 * called twice.
1851 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001852TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001853 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001854 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1855 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001856 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001857
1858 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001860 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1861 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001862 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001863
1864 // Window should receive motion event.
1865 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1866}
1867
1868/**
1869 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001870 */
1871TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001872 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001873 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1874 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001875 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001876
1877 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1878 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001879 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001880 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1881 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001882 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001883
1884 // Window should receive motion event.
1885 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1886}
1887
Arthur Hungb92218b2018-08-14 12:00:21 +08001888// The foreground window should receive the first touch down event.
1889TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001890 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001891 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001892 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001893 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001894 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001895
Arthur Hung72d8dc32020-03-28 00:48:39 +00001896 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1898 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1899 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001900
1901 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001902 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001903 windowSecond->assertNoEvents();
1904}
1905
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001906/**
1907 * Two windows: A top window, and a wallpaper behind the window.
1908 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1909 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001910 * 1. foregroundWindow <-- dup touch to wallpaper
1911 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001912 */
1913TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1914 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1915 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001916 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001917 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001918 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001919 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001920 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001921
1922 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1923 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1924 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1925 {100, 200}))
1926 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1927
1928 // Both foreground window and its wallpaper should receive the touch down
1929 foregroundWindow->consumeMotionDown();
1930 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1931
1932 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1933 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1934 ADISPLAY_ID_DEFAULT, {110, 200}))
1935 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1936
1937 foregroundWindow->consumeMotionMove();
1938 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1939
1940 // Now the foreground window goes away, but the wallpaper stays
1941 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1942 foregroundWindow->consumeMotionCancel();
1943 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1944 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1945}
1946
1947/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001948 * Two fingers down on the window, and lift off the first finger.
1949 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1950 * contains a single pointer.
1951 */
1952TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1953 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1954 sp<FakeWindowHandle> window =
1955 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1956
1957 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1958 NotifyMotionArgs args;
1959 // First touch pointer down on right window
1960 mDispatcher->notifyMotion(&(
1961 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1962 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
1963 .build()));
1964 // Second touch pointer down
1965 mDispatcher->notifyMotion(&(
1966 args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1967
1968 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
1969 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(110).y(100))
1970 .build()));
1971 // First touch pointer lifts. The second one remains down
1972 mDispatcher->notifyMotion(&(
1973 args = MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1974
1975 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
1976 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(110).y(100))
1977 .build()));
1978 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1979 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1980 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1981
1982 // Remove the window. The gesture should be canceled
1983 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
1984 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1985 window->consumeMotionEvent(
1986 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1987}
1988
1989/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001990 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1991 * with the following differences:
1992 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1993 * clean up the connection.
1994 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1995 * Ensure that there's no crash in the dispatcher.
1996 */
1997TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1998 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1999 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002000 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002001 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002002 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002003 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002004 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002005
2006 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
2007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2008 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2009 {100, 200}))
2010 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2011
2012 // Both foreground window and its wallpaper should receive the touch down
2013 foregroundWindow->consumeMotionDown();
2014 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2015
2016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2017 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2018 ADISPLAY_ID_DEFAULT, {110, 200}))
2019 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2020
2021 foregroundWindow->consumeMotionMove();
2022 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2023
2024 // Wallpaper closes its channel, but the window remains.
2025 wallpaperWindow->destroyReceiver();
2026 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
2027
2028 // Now the foreground window goes away, but the wallpaper stays, even though its channel
2029 // is no longer valid.
2030 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
2031 foregroundWindow->consumeMotionCancel();
2032}
2033
Arthur Hungc539dbb2022-12-08 07:45:36 +00002034class ShouldSplitTouchFixture : public InputDispatcherTest,
2035 public ::testing::WithParamInterface<bool> {};
2036INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
2037 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002038/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002039 * A single window that receives touch (on top), and a wallpaper window underneath it.
2040 * The top window gets a multitouch gesture.
2041 * Ensure that wallpaper gets the same gesture.
2042 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00002043TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002044 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002045 sp<FakeWindowHandle> foregroundWindow =
2046 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2047 foregroundWindow->setDupTouchToWallpaper(true);
2048 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002049
2050 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002051 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002052 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002053
Arthur Hungc539dbb2022-12-08 07:45:36 +00002054 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002055
2056 // Touch down on top window
2057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2058 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2059 {100, 100}))
2060 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2061
2062 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00002063 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002064 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2065
2066 // Second finger down on the top window
2067 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002068 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002069 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00002070 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2071 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002072 .build();
2073 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2074 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2075 InputEventInjectionSync::WAIT_FOR_RESULT))
2076 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2077
Harry Cutts33476232023-01-30 19:57:29 +00002078 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
2079 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002080 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002081
2082 const MotionEvent secondFingerUpEvent =
2083 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2084 .displayId(ADISPLAY_ID_DEFAULT)
2085 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00002086 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2087 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002088 .build();
2089 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2090 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
2091 InputEventInjectionSync::WAIT_FOR_RESULT))
2092 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2093 foregroundWindow->consumeMotionPointerUp(0);
2094 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2095
2096 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2097 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2098 {100, 100}))
2099 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2100 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2101 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002102}
2103
2104/**
2105 * Two windows: a window on the left and window on the right.
2106 * A third window, wallpaper, is behind both windows, and spans both top windows.
2107 * The first touch down goes to the left window. A second pointer touches down on the right window.
2108 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2109 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2110 * ACTION_POINTER_DOWN(1).
2111 */
2112TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2113 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2114 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002115 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002116 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002117 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002118
2119 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002120 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002121 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002122 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002123
2124 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002125 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002126 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002127 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002128
2129 mDispatcher->setInputWindows(
2130 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
2131
2132 // Touch down on left window
2133 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2134 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2135 {100, 100}))
2136 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2137
2138 // Both foreground window and its wallpaper should receive the touch down
2139 leftWindow->consumeMotionDown();
2140 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2141
2142 // Second finger down on the right window
2143 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002144 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002145 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00002146 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2147 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002148 .build();
2149 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2150 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2151 InputEventInjectionSync::WAIT_FOR_RESULT))
2152 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2153
2154 leftWindow->consumeMotionMove();
2155 // Since the touch is split, right window gets ACTION_DOWN
2156 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002157 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002158 expectedWallpaperFlags);
2159
2160 // Now, leftWindow, which received the first finger, disappears.
2161 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
2162 leftWindow->consumeMotionCancel();
2163 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2164 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2165
2166 // The pointer that's still down on the right window moves, and goes to the right window only.
2167 // As far as the dispatcher's concerned though, both pointers are still present.
2168 const MotionEvent secondFingerMoveEvent =
2169 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2170 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00002171 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2172 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002173 .build();
2174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2175 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2176 InputEventInjectionSync::WAIT_FOR_RESULT));
2177 rightWindow->consumeMotionMove();
2178
2179 leftWindow->assertNoEvents();
2180 rightWindow->assertNoEvents();
2181 wallpaperWindow->assertNoEvents();
2182}
2183
Arthur Hungc539dbb2022-12-08 07:45:36 +00002184/**
2185 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2186 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2187 * The right window should receive ACTION_DOWN.
2188 */
2189TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002190 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002191 sp<FakeWindowHandle> leftWindow =
2192 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2193 leftWindow->setFrame(Rect(0, 0, 200, 200));
2194 leftWindow->setDupTouchToWallpaper(true);
2195 leftWindow->setSlippery(true);
2196
2197 sp<FakeWindowHandle> rightWindow =
2198 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2199 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002200
2201 sp<FakeWindowHandle> wallpaperWindow =
2202 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2203 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002204
Arthur Hungc539dbb2022-12-08 07:45:36 +00002205 mDispatcher->setInputWindows(
2206 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002207
Arthur Hungc539dbb2022-12-08 07:45:36 +00002208 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2210 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002211 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002212 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002213
2214 // Both foreground window and its wallpaper should receive the touch down
2215 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002216 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2217
Arthur Hungc539dbb2022-12-08 07:45:36 +00002218 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002220 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2221 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002222 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2223
Arthur Hungc539dbb2022-12-08 07:45:36 +00002224 leftWindow->consumeMotionCancel();
2225 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2226 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002227}
2228
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002229/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002230 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2231 * interactive, it might stop sending this flag.
2232 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2233 * to have a consistent input stream.
2234 *
2235 * Test procedure:
2236 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2237 * DOWN (new gesture).
2238 *
2239 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2240 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2241 *
2242 * We technically just need a single window here, but we are using two windows (spy on top and a
2243 * regular window below) to emulate the actual situation where it happens on the device.
2244 */
2245TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2246 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2247 sp<FakeWindowHandle> spyWindow =
2248 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2249 spyWindow->setFrame(Rect(0, 0, 200, 200));
2250 spyWindow->setTrustedOverlay(true);
2251 spyWindow->setSpy(true);
2252
2253 sp<FakeWindowHandle> window =
2254 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2255 window->setFrame(Rect(0, 0, 200, 200));
2256
2257 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2258 const int32_t touchDeviceId = 4;
2259 NotifyMotionArgs args;
2260
2261 // Two pointers down
2262 mDispatcher->notifyMotion(&(
2263 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2264 .deviceId(touchDeviceId)
2265 .policyFlags(DEFAULT_POLICY_FLAGS)
2266 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2267 .build()));
2268
2269 mDispatcher->notifyMotion(&(
2270 args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2271 .deviceId(touchDeviceId)
2272 .policyFlags(DEFAULT_POLICY_FLAGS)
2273 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2274 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(120).y(120))
2275 .build()));
2276 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2277 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2278 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2279 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2280
2281 // Cancel the current gesture. Send the cancel without the default policy flags.
2282 mDispatcher->notifyMotion(&(
2283 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2284 .deviceId(touchDeviceId)
2285 .policyFlags(0)
2286 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2287 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(120).y(120))
2288 .build()));
2289 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2290 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2291
2292 // We don't need to reset the device to reproduce the issue, but the reset event typically
2293 // follows, so we keep it here to model the actual listener behaviour more closely.
2294 NotifyDeviceResetArgs resetArgs;
2295 resetArgs.id = 1; // arbitrary id
2296 resetArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
2297 resetArgs.deviceId = touchDeviceId;
2298 mDispatcher->notifyDeviceReset(&resetArgs);
2299
2300 // Start new gesture
2301 mDispatcher->notifyMotion(&(
2302 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2303 .deviceId(touchDeviceId)
2304 .policyFlags(DEFAULT_POLICY_FLAGS)
2305 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2306 .build()));
2307 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2308 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2309
2310 // No more events
2311 spyWindow->assertNoEvents();
2312 window->assertNoEvents();
2313}
2314
2315/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002316 * Two windows: a window on the left and a window on the right.
2317 * Mouse is hovered from the right window into the left window.
2318 * Next, we tap on the left window, where the cursor was last seen.
2319 * The second tap is done onto the right window.
2320 * The mouse and tap are from two different devices.
2321 * We technically don't need to set the downtime / eventtime for these events, but setting these
2322 * explicitly helps during debugging.
2323 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2324 * In the buggy implementation, a tap on the right window would cause a crash.
2325 */
2326TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2327 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2328 sp<FakeWindowHandle> leftWindow =
2329 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2330 leftWindow->setFrame(Rect(0, 0, 200, 200));
2331
2332 sp<FakeWindowHandle> rightWindow =
2333 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2334 rightWindow->setFrame(Rect(200, 0, 400, 200));
2335
2336 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2337 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2338 // stale.
2339 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2340 const int32_t mouseDeviceId = 6;
2341 const int32_t touchDeviceId = 4;
2342 // Move the cursor from right
2343 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2344 injectMotionEvent(mDispatcher,
2345 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2346 AINPUT_SOURCE_MOUSE)
2347 .deviceId(mouseDeviceId)
2348 .downTime(baseTime + 10)
2349 .eventTime(baseTime + 20)
2350 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2351 .x(300)
2352 .y(100))
2353 .build()));
2354 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2355
2356 // .. to the left window
2357 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2358 injectMotionEvent(mDispatcher,
2359 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2360 AINPUT_SOURCE_MOUSE)
2361 .deviceId(mouseDeviceId)
2362 .downTime(baseTime + 10)
2363 .eventTime(baseTime + 30)
2364 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2365 .x(110)
2366 .y(100))
2367 .build()));
2368 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2369 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2370 // Now tap the left window
2371 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2372 injectMotionEvent(mDispatcher,
2373 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2374 AINPUT_SOURCE_TOUCHSCREEN)
2375 .deviceId(touchDeviceId)
2376 .downTime(baseTime + 40)
2377 .eventTime(baseTime + 40)
2378 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2379 .x(100)
2380 .y(100))
2381 .build()));
2382 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2383 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2384
2385 // release tap
2386 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2387 injectMotionEvent(mDispatcher,
2388 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2389 AINPUT_SOURCE_TOUCHSCREEN)
2390 .deviceId(touchDeviceId)
2391 .downTime(baseTime + 40)
2392 .eventTime(baseTime + 50)
2393 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2394 .x(100)
2395 .y(100))
2396 .build()));
2397 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2398
2399 // Tap the window on the right
2400 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2401 injectMotionEvent(mDispatcher,
2402 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2403 AINPUT_SOURCE_TOUCHSCREEN)
2404 .deviceId(touchDeviceId)
2405 .downTime(baseTime + 60)
2406 .eventTime(baseTime + 60)
2407 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2408 .x(300)
2409 .y(100))
2410 .build()));
2411 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2412
2413 // release tap
2414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2415 injectMotionEvent(mDispatcher,
2416 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2417 AINPUT_SOURCE_TOUCHSCREEN)
2418 .deviceId(touchDeviceId)
2419 .downTime(baseTime + 60)
2420 .eventTime(baseTime + 70)
2421 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2422 .x(300)
2423 .y(100))
2424 .build()));
2425 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2426
2427 // No more events
2428 leftWindow->assertNoEvents();
2429 rightWindow->assertNoEvents();
2430}
2431
2432/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002433 * Two windows: a window on the left and a window on the right.
2434 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2435 * down. Then, on the left window, also place second touch pointer down.
2436 * This test tries to reproduce a crash.
2437 * In the buggy implementation, second pointer down on the left window would cause a crash.
2438 */
2439TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2440 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2441 sp<FakeWindowHandle> leftWindow =
2442 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2443 leftWindow->setFrame(Rect(0, 0, 200, 200));
2444
2445 sp<FakeWindowHandle> rightWindow =
2446 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2447 rightWindow->setFrame(Rect(200, 0, 400, 200));
2448
2449 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2450
2451 const int32_t touchDeviceId = 4;
2452 const int32_t mouseDeviceId = 6;
2453 NotifyMotionArgs args;
2454
2455 // Start hovering over the left window
2456 mDispatcher->notifyMotion(&(
2457 args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2458 .deviceId(mouseDeviceId)
2459 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(100).y(100))
2460 .build()));
2461 leftWindow->consumeMotionEvent(
2462 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2463
2464 // Mouse down on left window
2465 mDispatcher->notifyMotion(&(
2466 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2467 .deviceId(mouseDeviceId)
2468 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2469 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(100).y(100))
2470 .build()));
2471
2472 leftWindow->consumeMotionEvent(
2473 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2474 leftWindow->consumeMotionEvent(
2475 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2476
2477 mDispatcher->notifyMotion(&(
2478 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2479 .deviceId(mouseDeviceId)
2480 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2481 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2482 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(100).y(100))
2483 .build()));
2484 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2485
2486 // First touch pointer down on right window
2487 mDispatcher->notifyMotion(&(
2488 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2489 .deviceId(touchDeviceId)
2490 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(300).y(100))
2491 .build()));
2492 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2493
2494 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2495
2496 // Second touch pointer down on left window
2497 mDispatcher->notifyMotion(&(
2498 args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2499 .deviceId(touchDeviceId)
2500 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(300).y(100))
2501 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2502 .build()));
2503 leftWindow->consumeMotionEvent(
2504 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2505 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2506 // current implementation.
2507 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2508 rightWindow->consumeMotionEvent(
2509 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2510
2511 leftWindow->assertNoEvents();
2512 rightWindow->assertNoEvents();
2513}
2514
2515/**
2516 * On a single window, use two different devices: mouse and touch.
2517 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2518 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2519 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2520 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2521 * represent a new gesture.
2522 */
2523TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2524 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2525 sp<FakeWindowHandle> window =
2526 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2527 window->setFrame(Rect(0, 0, 400, 400));
2528
2529 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2530
2531 const int32_t touchDeviceId = 4;
2532 const int32_t mouseDeviceId = 6;
2533 NotifyMotionArgs args;
2534
2535 // First touch pointer down on right window
2536 mDispatcher->notifyMotion(&(
2537 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2538 .deviceId(touchDeviceId)
2539 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(300).y(100))
2540 .build()));
2541 // Second touch pointer down
2542 mDispatcher->notifyMotion(&(
2543 args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2544 .deviceId(touchDeviceId)
2545 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(300).y(100))
2546 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(350).y(100))
2547 .build()));
2548 // First touch pointer lifts. The second one remains down
2549 mDispatcher->notifyMotion(&(
2550 args = MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2551 .deviceId(touchDeviceId)
2552 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(300).y(100))
2553 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(350).y(100))
2554 .build()));
2555 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2556 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2557 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2558
2559 // Mouse down. The touch should be canceled
2560 mDispatcher->notifyMotion(&(
2561 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2562 .deviceId(mouseDeviceId)
2563 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2564 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(320).y(100))
2565 .build()));
2566
2567 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002568 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002569 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2570
2571 mDispatcher->notifyMotion(&(
2572 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2573 .deviceId(mouseDeviceId)
2574 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2575 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2576 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(320).y(100))
2577 .build()));
2578 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2579
2580 // Second touch pointer down.
2581 mDispatcher->notifyMotion(&(
2582 args = MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2583 .deviceId(touchDeviceId)
2584 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(300).y(100))
2585 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(350).y(100))
2586 .build()));
2587 // The pointer_down event should be ignored
2588 window->assertNoEvents();
2589}
2590
2591/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002592 * This test is similar to the test above, but the sequence of injected events is different.
2593 *
2594 * Two windows: a window on the left and a window on the right.
2595 * Mouse is hovered over the left window.
2596 * Next, we tap on the left window, where the cursor was last seen.
2597 *
2598 * After that, we inject one finger down onto the right window, and then a second finger down onto
2599 * the left window.
2600 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2601 * window (first), and then another on the left window (second).
2602 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2603 * In the buggy implementation, second finger down on the left window would cause a crash.
2604 */
2605TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2606 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2607 sp<FakeWindowHandle> leftWindow =
2608 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2609 leftWindow->setFrame(Rect(0, 0, 200, 200));
2610
2611 sp<FakeWindowHandle> rightWindow =
2612 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2613 rightWindow->setFrame(Rect(200, 0, 400, 200));
2614
2615 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2616
2617 const int32_t mouseDeviceId = 6;
2618 const int32_t touchDeviceId = 4;
2619 // Hover over the left window. Keep the cursor there.
2620 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2621 injectMotionEvent(mDispatcher,
2622 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2623 AINPUT_SOURCE_MOUSE)
2624 .deviceId(mouseDeviceId)
2625 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2626 .x(50)
2627 .y(50))
2628 .build()));
2629 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2630
2631 // Tap on left window
2632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2633 injectMotionEvent(mDispatcher,
2634 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2635 AINPUT_SOURCE_TOUCHSCREEN)
2636 .deviceId(touchDeviceId)
2637 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2638 .x(100)
2639 .y(100))
2640 .build()));
2641
2642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2643 injectMotionEvent(mDispatcher,
2644 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2645 AINPUT_SOURCE_TOUCHSCREEN)
2646 .deviceId(touchDeviceId)
2647 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2648 .x(100)
2649 .y(100))
2650 .build()));
2651 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2652 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2653 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2654
2655 // First finger down on right window
2656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2657 injectMotionEvent(mDispatcher,
2658 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2659 AINPUT_SOURCE_TOUCHSCREEN)
2660 .deviceId(touchDeviceId)
2661 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2662 .x(300)
2663 .y(100))
2664 .build()));
2665 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2666
2667 // Second finger down on the left window
2668 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2669 injectMotionEvent(mDispatcher,
2670 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2671 .deviceId(touchDeviceId)
2672 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2673 .x(300)
2674 .y(100))
2675 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER)
2676 .x(100)
2677 .y(100))
2678 .build()));
2679 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2680 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2681
2682 // No more events
2683 leftWindow->assertNoEvents();
2684 rightWindow->assertNoEvents();
2685}
2686
2687/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002688 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2689 * While the touch is down, new hover events from the stylus device should be ignored. After the
2690 * touch is gone, stylus hovering should start working again.
2691 */
2692TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2693 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2694 sp<FakeWindowHandle> window =
2695 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2696 window->setFrame(Rect(0, 0, 200, 200));
2697
2698 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2699
2700 const int32_t stylusDeviceId = 5;
2701 const int32_t touchDeviceId = 4;
2702 // Start hovering with stylus
2703 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2704 injectMotionEvent(mDispatcher,
2705 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2706 AINPUT_SOURCE_STYLUS)
2707 .deviceId(stylusDeviceId)
2708 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
2709 .x(50)
2710 .y(50))
2711 .build()));
2712 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2713
2714 // Finger down on the window
2715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2716 injectMotionEvent(mDispatcher,
2717 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2718 AINPUT_SOURCE_TOUCHSCREEN)
2719 .deviceId(touchDeviceId)
2720 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2721 .x(100)
2722 .y(100))
2723 .build()));
2724 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2725 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2726
2727 // Try to continue hovering with stylus. Since we are already down, injection should fail
2728 ASSERT_EQ(InputEventInjectionResult::FAILED,
2729 injectMotionEvent(mDispatcher,
2730 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2731 AINPUT_SOURCE_STYLUS)
2732 .deviceId(stylusDeviceId)
2733 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
2734 .x(50)
2735 .y(50))
2736 .build()));
2737 // No event should be sent. This event should be ignored because a pointer from another device
2738 // is already down.
2739
2740 // Lift up the finger
2741 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2742 injectMotionEvent(mDispatcher,
2743 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2744 AINPUT_SOURCE_TOUCHSCREEN)
2745 .deviceId(touchDeviceId)
2746 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2747 .x(100)
2748 .y(100))
2749 .build()));
2750 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2751
2752 // Now that the touch is gone, stylus hovering should start working again
2753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2754 injectMotionEvent(mDispatcher,
2755 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2756 AINPUT_SOURCE_STYLUS)
2757 .deviceId(stylusDeviceId)
2758 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
2759 .x(50)
2760 .y(50))
2761 .build()));
2762 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2763 // No more events
2764 window->assertNoEvents();
2765}
2766
2767/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002768 * A spy window above a window with no input channel.
2769 * Start hovering with a stylus device, and then tap with it.
2770 * Ensure spy window receives the entire sequence.
2771 */
2772TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2773 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2774 sp<FakeWindowHandle> spyWindow =
2775 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2776 spyWindow->setFrame(Rect(0, 0, 200, 200));
2777 spyWindow->setTrustedOverlay(true);
2778 spyWindow->setSpy(true);
2779 sp<FakeWindowHandle> window =
2780 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2781 window->setNoInputChannel(true);
2782 window->setFrame(Rect(0, 0, 200, 200));
2783
2784 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2785
2786 NotifyMotionArgs args;
2787
2788 // Start hovering with stylus
2789 mDispatcher->notifyMotion(
2790 &(args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2791 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS).x(50).y(50))
2792 .build()));
2793 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2794 // Stop hovering
2795 mDispatcher->notifyMotion(
2796 &(args = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2797 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS).x(50).y(50))
2798 .build()));
2799 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2800
2801 // Stylus touches down
2802 mDispatcher->notifyMotion(
2803 &(args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2804 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS).x(50).y(50))
2805 .build()));
2806 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2807
2808 // Stylus goes up
2809 mDispatcher->notifyMotion(
2810 &(args = MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2811 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS).x(50).y(50))
2812 .build()));
2813 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2814
2815 // Again hover
2816 mDispatcher->notifyMotion(
2817 &(args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2818 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS).x(50).y(50))
2819 .build()));
2820 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2821 // Stop hovering
2822 mDispatcher->notifyMotion(
2823 &(args = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2824 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS).x(50).y(50))
2825 .build()));
2826 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2827
2828 // No more events
2829 spyWindow->assertNoEvents();
2830 window->assertNoEvents();
2831}
2832
2833/**
2834 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2835 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2836 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2837 * While the mouse is down, new move events from the touch device should be ignored.
2838 */
2839TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2840 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2841 sp<FakeWindowHandle> spyWindow =
2842 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2843 spyWindow->setFrame(Rect(0, 0, 200, 200));
2844 spyWindow->setTrustedOverlay(true);
2845 spyWindow->setSpy(true);
2846 sp<FakeWindowHandle> window =
2847 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2848 window->setFrame(Rect(0, 0, 200, 200));
2849
2850 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2851
2852 const int32_t mouseDeviceId = 7;
2853 const int32_t touchDeviceId = 4;
2854 NotifyMotionArgs args;
2855
2856 // Hover a bit with mouse first
2857 mDispatcher->notifyMotion(&(
2858 args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2859 .deviceId(mouseDeviceId)
2860 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(100).y(100))
2861 .build()));
2862 spyWindow->consumeMotionEvent(
2863 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2864 window->consumeMotionEvent(
2865 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2866
2867 // Start touching
2868 mDispatcher->notifyMotion(
2869 &(args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2870 .deviceId(touchDeviceId)
2871 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
2872 .build()));
2873 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2874 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2875 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2876 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2877
2878 mDispatcher->notifyMotion(
2879 &(args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2880 .deviceId(touchDeviceId)
2881 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(55).y(55))
2882 .build()));
2883 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2884 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2885
2886 // Pilfer the stream
2887 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2888 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2889
2890 mDispatcher->notifyMotion(
2891 &(args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2892 .deviceId(touchDeviceId)
2893 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(60).y(60))
2894 .build()));
2895 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2896
2897 // Mouse down
2898 mDispatcher->notifyMotion(&(
2899 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2900 .deviceId(mouseDeviceId)
2901 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2902 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(100).y(100))
2903 .build()));
2904
2905 spyWindow->consumeMotionEvent(
2906 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2907 spyWindow->consumeMotionEvent(
2908 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2909 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2910
2911 mDispatcher->notifyMotion(&(
2912 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2913 .deviceId(mouseDeviceId)
2914 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2915 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2916 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(100).y(100))
2917 .build()));
2918 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2919 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2920
2921 // Mouse move!
2922 mDispatcher->notifyMotion(&(
2923 args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2924 .deviceId(mouseDeviceId)
2925 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2926 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(110).y(110))
2927 .build()));
2928 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2929 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2930
2931 // Touch move!
2932 mDispatcher->notifyMotion(
2933 &(args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2934 .deviceId(touchDeviceId)
2935 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(65).y(65))
2936 .build()));
2937
2938 // No more events
2939 spyWindow->assertNoEvents();
2940 window->assertNoEvents();
2941}
2942
2943/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002944 * On the display, have a single window, and also an area where there's no window.
2945 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2946 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2947 */
2948TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2949 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2950 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002951 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002952
2953 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
2954 NotifyMotionArgs args;
2955
2956 // Touch down on the empty space
2957 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}})));
2958
2959 mDispatcher->waitForIdle();
2960 window->assertNoEvents();
2961
2962 // Now touch down on the window with another pointer
2963 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}})));
2964 mDispatcher->waitForIdle();
2965 window->consumeMotionDown();
2966}
2967
2968/**
2969 * Same test as above, but instead of touching the empty space, the first touch goes to
2970 * non-touchable window.
2971 */
2972TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2973 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2974 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002975 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002976 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2977 window1->setTouchable(false);
2978 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002979 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002980 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2981
2982 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2983
2984 NotifyMotionArgs args;
2985 // Touch down on the non-touchable window
2986 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})));
2987
2988 mDispatcher->waitForIdle();
2989 window1->assertNoEvents();
2990 window2->assertNoEvents();
2991
2992 // Now touch down on the window with another pointer
2993 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
2994 mDispatcher->waitForIdle();
2995 window2->consumeMotionDown();
2996}
2997
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002998/**
2999 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3000 * to the event time of the first ACTION_DOWN sent to the particular window.
3001 */
3002TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3003 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3004 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003005 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003006 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3007 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003008 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003009 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3010
3011 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
3012
3013 NotifyMotionArgs args;
3014 // Touch down on the first window
3015 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})));
3016
3017 mDispatcher->waitForIdle();
3018 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003019 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003020 window2->assertNoEvents();
3021 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
3022 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
3023 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
3024
3025 // Now touch down on the window with another pointer
3026 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
3027 mDispatcher->waitForIdle();
3028 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003029 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003030 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
3031 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
3032 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
3033 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
3034
3035 // Now move the pointer on the second window
3036 mDispatcher->notifyMotion(
3037 &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}})));
3038 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003039 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003040
3041 // Now add new touch down on the second window
3042 mDispatcher->notifyMotion(
3043 &(args = generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}})));
3044 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003045 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003046
3047 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3048 window1->consumeMotionMove();
3049 window1->assertNoEvents();
3050
3051 // Now move the pointer on the first window
3052 mDispatcher->notifyMotion(
3053 &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}})));
3054 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003055 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003056
3057 mDispatcher->notifyMotion(&(
3058 args = generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}})));
3059 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003060 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003061}
3062
Garfield Tandf26e862020-07-01 20:18:19 -07003063TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003064 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003065 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003066 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003067 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003068 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003069 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003070 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003071
3072 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3073
3074 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3075
3076 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003078 injectMotionEvent(mDispatcher,
3079 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3080 AINPUT_SOURCE_MOUSE)
3081 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3082 .x(900)
3083 .y(400))
3084 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003085 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003086
3087 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003089 injectMotionEvent(mDispatcher,
3090 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3091 AINPUT_SOURCE_MOUSE)
3092 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3093 .x(300)
3094 .y(400))
3095 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003096 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3097 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003098
3099 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003100 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003101 injectMotionEvent(mDispatcher,
3102 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3103 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3104 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3105 .x(300)
3106 .y(400))
3107 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003108 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3109 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003110
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003111 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003112 injectMotionEvent(mDispatcher,
3113 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3114 AINPUT_SOURCE_MOUSE)
3115 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3116 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3117 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3118 .x(300)
3119 .y(400))
3120 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003121 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003122
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003123 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003124 injectMotionEvent(mDispatcher,
3125 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3126 AINPUT_SOURCE_MOUSE)
3127 .buttonState(0)
3128 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3129 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3130 .x(300)
3131 .y(400))
3132 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003133 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003134
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003135 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003136 injectMotionEvent(mDispatcher,
3137 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3138 .buttonState(0)
3139 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3140 .x(300)
3141 .y(400))
3142 .build()));
3143 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3144
3145 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003146 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003147 injectMotionEvent(mDispatcher,
3148 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3149 AINPUT_SOURCE_MOUSE)
3150 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3151 .x(900)
3152 .y(400))
3153 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003154 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003155
3156 // No more events
3157 windowLeft->assertNoEvents();
3158 windowRight->assertNoEvents();
3159}
3160
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003161/**
3162 * Put two fingers down (and don't release them) and click the mouse button.
3163 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3164 * currently active gesture should be canceled, and the new one should proceed.
3165 */
3166TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3167 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3168 sp<FakeWindowHandle> window =
3169 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3170 window->setFrame(Rect(0, 0, 600, 800));
3171
3172 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3173
3174 const int32_t touchDeviceId = 4;
3175 const int32_t mouseDeviceId = 6;
3176 NotifyMotionArgs args;
3177
3178 // Two pointers down
3179 mDispatcher->notifyMotion(&(
3180 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3181 .deviceId(touchDeviceId)
3182 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
3183 .build()));
3184
3185 mDispatcher->notifyMotion(&(
3186 args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3187 .deviceId(touchDeviceId)
3188 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
3189 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(120).y(120))
3190 .build()));
3191 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3192 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3193
3194 // Inject a series of mouse events for a mouse click
3195 mDispatcher->notifyMotion(&(
3196 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3197 .deviceId(mouseDeviceId)
3198 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3199 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(300).y(400))
3200 .build()));
3201 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3202 WithPointerCount(2u)));
3203 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3204
3205 mDispatcher->notifyMotion(&(
3206 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3207 .deviceId(mouseDeviceId)
3208 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3209 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3210 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(300).y(400))
3211 .build()));
3212 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3213
3214 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3215 // already canceled gesture, it should be ignored.
3216 mDispatcher->notifyMotion(&(
3217 args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3218 .deviceId(touchDeviceId)
3219 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(101).y(101))
3220 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(121).y(121))
3221 .build()));
3222 window->assertNoEvents();
3223}
3224
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003225TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3226 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3227
3228 sp<FakeWindowHandle> spyWindow =
3229 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3230 spyWindow->setFrame(Rect(0, 0, 600, 800));
3231 spyWindow->setTrustedOverlay(true);
3232 spyWindow->setSpy(true);
3233 sp<FakeWindowHandle> window =
3234 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3235 window->setFrame(Rect(0, 0, 600, 800));
3236
3237 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3238 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3239
3240 // Send mouse cursor to the window
3241 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3242 injectMotionEvent(mDispatcher,
3243 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3244 AINPUT_SOURCE_MOUSE)
3245 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3246 .x(100)
3247 .y(100))
3248 .build()));
3249
3250 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3251 WithSource(AINPUT_SOURCE_MOUSE)));
3252 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3253 WithSource(AINPUT_SOURCE_MOUSE)));
3254
3255 window->assertNoEvents();
3256 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003257}
3258
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003259TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3260 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3261
3262 sp<FakeWindowHandle> spyWindow =
3263 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3264 spyWindow->setFrame(Rect(0, 0, 600, 800));
3265 spyWindow->setTrustedOverlay(true);
3266 spyWindow->setSpy(true);
3267 sp<FakeWindowHandle> window =
3268 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3269 window->setFrame(Rect(0, 0, 600, 800));
3270
3271 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3272 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3273
3274 // Send mouse cursor to the window
3275 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3276 injectMotionEvent(mDispatcher,
3277 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3278 AINPUT_SOURCE_MOUSE)
3279 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3280 .x(100)
3281 .y(100))
3282 .build()));
3283
3284 // Move mouse cursor
3285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3286 injectMotionEvent(mDispatcher,
3287 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3288 AINPUT_SOURCE_MOUSE)
3289 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3290 .x(110)
3291 .y(110))
3292 .build()));
3293
3294 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3295 WithSource(AINPUT_SOURCE_MOUSE)));
3296 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3297 WithSource(AINPUT_SOURCE_MOUSE)));
3298 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3299 WithSource(AINPUT_SOURCE_MOUSE)));
3300 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3301 WithSource(AINPUT_SOURCE_MOUSE)));
3302 // Touch down on the window
3303 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3304 injectMotionEvent(mDispatcher,
3305 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3306 AINPUT_SOURCE_TOUCHSCREEN)
3307 .deviceId(SECOND_DEVICE_ID)
3308 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
3309 .x(200)
3310 .y(200))
3311 .build()));
3312 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3313 WithSource(AINPUT_SOURCE_MOUSE)));
3314 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3315 WithSource(AINPUT_SOURCE_MOUSE)));
3316 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3317 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3318 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3319 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3320
3321 // pilfer the motion, retaining the gesture on the spy window.
3322 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3323 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3324 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3325
3326 // Touch UP on the window
3327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3328 injectMotionEvent(mDispatcher,
3329 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3330 AINPUT_SOURCE_TOUCHSCREEN)
3331 .deviceId(SECOND_DEVICE_ID)
3332 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
3333 .x(200)
3334 .y(200))
3335 .build()));
3336 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3337 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3338
3339 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3340 // to send a new gesture. It should again go to both windows (spy and the window below), just
3341 // like the first gesture did, before pilfering. The window configuration has not changed.
3342
3343 // One more tap - DOWN
3344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3345 injectMotionEvent(mDispatcher,
3346 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3347 AINPUT_SOURCE_TOUCHSCREEN)
3348 .deviceId(SECOND_DEVICE_ID)
3349 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
3350 .x(250)
3351 .y(250))
3352 .build()));
3353 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3354 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3355 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3356 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3357
3358 // Touch UP on the window
3359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3360 injectMotionEvent(mDispatcher,
3361 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3362 AINPUT_SOURCE_TOUCHSCREEN)
3363 .deviceId(SECOND_DEVICE_ID)
3364 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
3365 .x(250)
3366 .y(250))
3367 .build()));
3368 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3369 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3370 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3371 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3372
3373 window->assertNoEvents();
3374 spyWindow->assertNoEvents();
3375}
3376
Garfield Tandf26e862020-07-01 20:18:19 -07003377// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3378// directly in this test.
3379TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003380 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003381 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003382 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003383 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003384
3385 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3386
3387 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3388
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003389 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003390 injectMotionEvent(mDispatcher,
3391 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3392 AINPUT_SOURCE_MOUSE)
3393 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3394 .x(300)
3395 .y(400))
3396 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003397 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003398 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003399 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003400 injectMotionEvent(mDispatcher,
3401 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3402 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3403 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3404 .x(300)
3405 .y(400))
3406 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003407 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3408 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003409
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003411 injectMotionEvent(mDispatcher,
3412 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3413 AINPUT_SOURCE_MOUSE)
3414 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3415 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3416 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3417 .x(300)
3418 .y(400))
3419 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003420 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003421
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003422 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003423 injectMotionEvent(mDispatcher,
3424 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3425 AINPUT_SOURCE_MOUSE)
3426 .buttonState(0)
3427 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3428 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3429 .x(300)
3430 .y(400))
3431 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003432 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003433
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003434 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003435 injectMotionEvent(mDispatcher,
3436 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3437 .buttonState(0)
3438 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3439 .x(300)
3440 .y(400))
3441 .build()));
3442 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3443
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003444 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003445 injectMotionEvent(mDispatcher,
3446 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3447 AINPUT_SOURCE_MOUSE)
3448 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3449 .x(300)
3450 .y(400))
3451 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003452 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003453}
3454
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003455/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003456 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3457 * is generated.
3458 */
3459TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3460 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3461 sp<FakeWindowHandle> window =
3462 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3463 window->setFrame(Rect(0, 0, 1200, 800));
3464
3465 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3466
3467 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3468
3469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3470 injectMotionEvent(mDispatcher,
3471 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3472 AINPUT_SOURCE_MOUSE)
3473 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3474 .x(300)
3475 .y(400))
3476 .build()));
3477 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3478
3479 // Remove the window, but keep the channel.
3480 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3481 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3482}
3483
3484/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003485 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003486 * The tap causes a HOVER_EXIT event to be generated because the current event
3487 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003488 */
3489TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3490 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3491 sp<FakeWindowHandle> window =
3492 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3493 window->setFrame(Rect(0, 0, 100, 100));
3494
3495 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3496
3497 // Inject a hover_move from mouse.
3498 NotifyMotionArgs motionArgs =
3499 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3500 ADISPLAY_ID_DEFAULT, {{50, 50}});
3501 motionArgs.xCursorPosition = 50;
3502 motionArgs.yCursorPosition = 50;
3503 mDispatcher->notifyMotion(&motionArgs);
3504 ASSERT_NO_FATAL_FAILURE(
3505 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3506 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003507
3508 // Tap on the window
3509 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3510 ADISPLAY_ID_DEFAULT, {{10, 10}});
3511 mDispatcher->notifyMotion(&motionArgs);
3512 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003513 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3514 WithSource(AINPUT_SOURCE_MOUSE))));
3515
3516 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003517 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3518 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3519
3520 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3521 ADISPLAY_ID_DEFAULT, {{10, 10}});
3522 mDispatcher->notifyMotion(&motionArgs);
3523 ASSERT_NO_FATAL_FAILURE(
3524 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3525 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3526}
3527
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003528TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3529 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3530 sp<FakeWindowHandle> windowDefaultDisplay =
3531 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3532 ADISPLAY_ID_DEFAULT);
3533 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3534 sp<FakeWindowHandle> windowSecondDisplay =
3535 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3536 SECOND_DISPLAY_ID);
3537 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3538
3539 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3540 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3541
3542 // Set cursor position in window in default display and check that hover enter and move
3543 // events are generated.
3544 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3545 injectMotionEvent(mDispatcher,
3546 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3547 AINPUT_SOURCE_MOUSE)
3548 .displayId(ADISPLAY_ID_DEFAULT)
3549 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3550 .x(300)
3551 .y(600))
3552 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003553 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003554
3555 // Remove all windows in secondary display and check that no event happens on window in
3556 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003557 mDispatcher->setInputWindows(
3558 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003559 windowDefaultDisplay->assertNoEvents();
3560
3561 // Move cursor position in window in default display and check that only hover move
3562 // event is generated and not hover enter event.
3563 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3564 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3565 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3566 injectMotionEvent(mDispatcher,
3567 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3568 AINPUT_SOURCE_MOUSE)
3569 .displayId(ADISPLAY_ID_DEFAULT)
3570 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3571 .x(400)
3572 .y(700))
3573 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003574 windowDefaultDisplay->consumeMotionEvent(
3575 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3576 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003577 windowDefaultDisplay->assertNoEvents();
3578}
3579
Garfield Tan00f511d2019-06-12 16:55:40 -07003580TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003581 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003582
3583 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003584 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003585 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003586 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003587 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003588 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003589
3590 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3591
Arthur Hung72d8dc32020-03-28 00:48:39 +00003592 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003593
3594 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3595 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003597 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003598 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003599 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003600 windowRight->assertNoEvents();
3601}
3602
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003603TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003604 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003605 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3606 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003607 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003608
Arthur Hung72d8dc32020-03-28 00:48:39 +00003609 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003610 setFocusedWindow(window);
3611
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003612 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003613
3614 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3615 mDispatcher->notifyKey(&keyArgs);
3616
3617 // Window should receive key down event.
3618 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3619
3620 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3621 // on the app side.
Harry Cutts33476232023-01-30 19:57:29 +00003622 NotifyDeviceResetArgs args(/*id=*/10, /*eventTime=*/20, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003623 mDispatcher->notifyDeviceReset(&args);
3624 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
3625 AKEY_EVENT_FLAG_CANCELED);
3626}
3627
3628TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003629 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003630 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3631 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003632
Arthur Hung72d8dc32020-03-28 00:48:39 +00003633 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003634
3635 NotifyMotionArgs motionArgs =
3636 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3637 ADISPLAY_ID_DEFAULT);
3638 mDispatcher->notifyMotion(&motionArgs);
3639
3640 // Window should receive motion down event.
3641 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3642
3643 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3644 // on the app side.
Harry Cutts33476232023-01-30 19:57:29 +00003645 NotifyDeviceResetArgs args(/*id=*/10, /*eventTime=*/20, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003646 mDispatcher->notifyDeviceReset(&args);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003647 window->consumeMotionEvent(
3648 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003649}
3650
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003651TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3652 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003653 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3654 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003655 window->setFocusable(true);
3656
3657 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3658 setFocusedWindow(window);
3659
3660 window->consumeFocusEvent(true);
3661
3662 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3663 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3664 const nsecs_t injectTime = keyArgs.eventTime;
3665 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
3666 mDispatcher->notifyKey(&keyArgs);
3667 // The dispatching time should be always greater than or equal to intercept key timeout.
3668 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3669 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3670 std::chrono::nanoseconds(interceptKeyTimeout).count());
3671}
3672
3673TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3674 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003675 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3676 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003677 window->setFocusable(true);
3678
3679 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3680 setFocusedWindow(window);
3681
3682 window->consumeFocusEvent(true);
3683
3684 NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3685 NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3686 mFakePolicy->setInterceptKeyTimeout(150ms);
3687 mDispatcher->notifyKey(&keyDown);
3688 mDispatcher->notifyKey(&keyUp);
3689
3690 // Window should receive key event immediately when same key up.
3691 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3692 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3693}
3694
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003695/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003696 * Two windows. First is a regular window. Second does not overlap with the first, and has
3697 * WATCH_OUTSIDE_TOUCH.
3698 * Both windows are owned by the same UID.
3699 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3700 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3701 */
3702TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3704 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3705 "First Window", ADISPLAY_ID_DEFAULT);
3706 window->setFrame(Rect{0, 0, 100, 100});
3707
3708 sp<FakeWindowHandle> outsideWindow =
3709 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3710 ADISPLAY_ID_DEFAULT);
3711 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3712 outsideWindow->setWatchOutsideTouch(true);
3713 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3714 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3715
3716 // Tap on first window.
3717 NotifyMotionArgs motionArgs =
3718 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3719 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
3720 mDispatcher->notifyMotion(&motionArgs);
3721 window->consumeMotionDown();
3722 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3723 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3724 outsideWindow->consumeMotionEvent(
3725 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3726}
3727
3728/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003729 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3730 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3731 * ACTION_OUTSIDE event is sent per gesture.
3732 */
3733TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3734 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3735 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003736 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3737 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003738 window->setWatchOutsideTouch(true);
3739 window->setFrame(Rect{0, 0, 100, 100});
3740 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003741 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3742 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003743 secondWindow->setFrame(Rect{100, 100, 200, 200});
3744 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003745 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3746 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003747 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3748 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3749
3750 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
3751 NotifyMotionArgs motionArgs =
3752 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3753 ADISPLAY_ID_DEFAULT, {PointF{-10, -10}});
3754 mDispatcher->notifyMotion(&motionArgs);
3755 window->assertNoEvents();
3756 secondWindow->assertNoEvents();
3757
3758 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3759 // Now, `window` should get ACTION_OUTSIDE.
3760 motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3761 {PointF{-10, -10}, PointF{105, 105}});
3762 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003763 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3764 window->consumeMotionEvent(
3765 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003766 secondWindow->consumeMotionDown();
3767 thirdWindow->assertNoEvents();
3768
3769 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3770 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
3771 motionArgs = generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3772 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}});
3773 mDispatcher->notifyMotion(&motionArgs);
3774 window->assertNoEvents();
3775 secondWindow->consumeMotionMove();
3776 thirdWindow->consumeMotionDown();
3777}
3778
Prabir Pradhan814fe082022-07-22 20:22:18 +00003779TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3780 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003781 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3782 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003783 window->setFocusable(true);
3784
3785 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
3786 setFocusedWindow(window);
3787
3788 window->consumeFocusEvent(true);
3789
3790 NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3791 NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3792 mDispatcher->notifyKey(&keyDown);
3793 mDispatcher->notifyKey(&keyUp);
3794
3795 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3796 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3797
3798 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
3799 mDispatcher->onWindowInfosChanged({}, {});
3800
3801 window->consumeFocusEvent(false);
3802
3803 mDispatcher->notifyKey(&keyDown);
3804 mDispatcher->notifyKey(&keyUp);
3805 window->assertNoEvents();
3806}
3807
Arthur Hung96483742022-11-15 03:30:48 +00003808TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3809 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3810 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3811 "Fake Window", ADISPLAY_ID_DEFAULT);
3812 // Ensure window is non-split and have some transform.
3813 window->setPreventSplitting(true);
3814 window->setWindowOffset(20, 40);
3815 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
3816
3817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3818 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3819 {50, 50}))
3820 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3821 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3822
3823 const MotionEvent secondFingerDownEvent =
3824 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3825 .displayId(ADISPLAY_ID_DEFAULT)
3826 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00003827 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
3828 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003829 .build();
3830 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3831 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3832 InputEventInjectionSync::WAIT_FOR_RESULT))
3833 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3834
3835 const MotionEvent* event = window->consumeMotion();
3836 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3837 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3838 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3839 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3840 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3841}
3842
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003843/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003844 * Ensure the correct coordinate spaces are used by InputDispatcher.
3845 *
3846 * InputDispatcher works in the display space, so its coordinate system is relative to the display
3847 * panel. Windows get events in the window space, and get raw coordinates in the logical display
3848 * space.
3849 */
3850class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
3851public:
3852 void SetUp() override {
3853 InputDispatcherTest::SetUp();
3854 mDisplayInfos.clear();
3855 mWindowInfos.clear();
3856 }
3857
3858 void addDisplayInfo(int displayId, const ui::Transform& transform) {
3859 gui::DisplayInfo info;
3860 info.displayId = displayId;
3861 info.transform = transform;
3862 mDisplayInfos.push_back(std::move(info));
3863 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
3864 }
3865
3866 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
3867 mWindowInfos.push_back(*windowHandle->getInfo());
3868 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
3869 }
3870
3871 // Set up a test scenario where the display has a scaled projection and there are two windows
3872 // on the display.
3873 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
3874 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
3875 // respectively.
3876 ui::Transform displayTransform;
3877 displayTransform.set(2, 0, 0, 4);
3878 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
3879
3880 std::shared_ptr<FakeApplicationHandle> application =
3881 std::make_shared<FakeApplicationHandle>();
3882
3883 // Add two windows to the display. Their frames are represented in the display space.
3884 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003885 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3886 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003887 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
3888 addWindow(firstWindow);
3889
3890 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003891 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3892 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003893 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
3894 addWindow(secondWindow);
3895 return {std::move(firstWindow), std::move(secondWindow)};
3896 }
3897
3898private:
3899 std::vector<gui::DisplayInfo> mDisplayInfos;
3900 std::vector<gui::WindowInfo> mWindowInfos;
3901};
3902
3903TEST_F(InputDispatcherDisplayProjectionTest, HitTestsInDisplaySpace) {
3904 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3905 // Send down to the first window. The point is represented in the display space. The point is
3906 // selected so that if the hit test was done with the transform applied to it, then it would
3907 // end up in the incorrect window.
3908 NotifyMotionArgs downMotionArgs =
3909 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3910 ADISPLAY_ID_DEFAULT, {PointF{75, 55}});
3911 mDispatcher->notifyMotion(&downMotionArgs);
3912
3913 firstWindow->consumeMotionDown();
3914 secondWindow->assertNoEvents();
3915}
3916
3917// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
3918// the event should be treated as being in the logical display space.
3919TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
3920 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3921 // Send down to the first window. The point is represented in the logical display space. The
3922 // point is selected so that if the hit test was done in logical display space, then it would
3923 // end up in the incorrect window.
3924 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3925 PointF{75 * 2, 55 * 4});
3926
3927 firstWindow->consumeMotionDown();
3928 secondWindow->assertNoEvents();
3929}
3930
Prabir Pradhandaa2f142021-12-10 09:30:08 +00003931// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
3932// event should be treated as being in the logical display space.
3933TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
3934 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3935
3936 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
3937 ui::Transform injectedEventTransform;
3938 injectedEventTransform.set(matrix);
3939 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
3940 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
3941
3942 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3943 .displayId(ADISPLAY_ID_DEFAULT)
3944 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00003945 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00003946 .x(untransformedPoint.x)
3947 .y(untransformedPoint.y))
3948 .build();
3949 event.transform(matrix);
3950
3951 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
3952 InputEventInjectionSync::WAIT_FOR_RESULT);
3953
3954 firstWindow->consumeMotionDown();
3955 secondWindow->assertNoEvents();
3956}
3957
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003958TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
3959 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3960
3961 // Send down to the second window.
3962 NotifyMotionArgs downMotionArgs =
3963 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3964 ADISPLAY_ID_DEFAULT, {PointF{150, 220}});
3965 mDispatcher->notifyMotion(&downMotionArgs);
3966
3967 firstWindow->assertNoEvents();
3968 const MotionEvent* event = secondWindow->consumeMotion();
3969 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
3970
3971 // Ensure that the events from the "getRaw" API are in logical display coordinates.
3972 EXPECT_EQ(300, event->getRawX(0));
3973 EXPECT_EQ(880, event->getRawY(0));
3974
3975 // Ensure that the x and y values are in the window's coordinate space.
3976 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
3977 // the logical display space. This will be the origin of the window space.
3978 EXPECT_EQ(100, event->getX(0));
3979 EXPECT_EQ(80, event->getY(0));
3980}
3981
Siarhei Vishniakou18050092021-09-01 13:32:49 -07003982using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
3983 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003984
3985class TransferTouchFixture : public InputDispatcherTest,
3986 public ::testing::WithParamInterface<TransferFunction> {};
3987
3988TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07003989 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08003990
3991 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003992 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003993 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3994 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00003995 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003996 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003997 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3998 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00003999 sp<FakeWindowHandle> wallpaper =
4000 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4001 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004002 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004003 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004004
4005 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004006 NotifyMotionArgs downMotionArgs =
4007 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4008 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004009 mDispatcher->notifyMotion(&downMotionArgs);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004010
Svet Ganov5d3bc372020-01-26 23:11:07 -08004011 // Only the first window should get the down event
4012 firstWindow->consumeMotionDown();
4013 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004014 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004015
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004016 // Transfer touch to the second window
4017 TransferFunction f = GetParam();
4018 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4019 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004020 // The first window gets cancel and the second gets down
4021 firstWindow->consumeMotionCancel();
4022 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004023 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004024
4025 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004026 NotifyMotionArgs upMotionArgs =
4027 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4028 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004029 mDispatcher->notifyMotion(&upMotionArgs);
4030 // The first window gets no events and the second gets up
4031 firstWindow->assertNoEvents();
4032 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004033 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004034}
4035
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004036/**
4037 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4038 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4039 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4040 * natural to the user.
4041 * In this test, we are sending a pointer to both spy window and first window. We then try to
4042 * transfer touch to the second window. The dispatcher should identify the first window as the
4043 * one that should lose the gesture, and therefore the action should be to move the gesture from
4044 * the first window to the second.
4045 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4046 * the other API, as well.
4047 */
4048TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4049 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4050
4051 // Create a couple of windows + a spy window
4052 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004053 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004054 spyWindow->setTrustedOverlay(true);
4055 spyWindow->setSpy(true);
4056 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004057 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004058 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004059 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004060
4061 // Add the windows to the dispatcher
4062 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4063
4064 // Send down to the first window
4065 NotifyMotionArgs downMotionArgs =
4066 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4067 ADISPLAY_ID_DEFAULT);
4068 mDispatcher->notifyMotion(&downMotionArgs);
4069 // Only the first window and spy should get the down event
4070 spyWindow->consumeMotionDown();
4071 firstWindow->consumeMotionDown();
4072
4073 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4074 // if f === 'transferTouch'.
4075 TransferFunction f = GetParam();
4076 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4077 ASSERT_TRUE(success);
4078 // The first window gets cancel and the second gets down
4079 firstWindow->consumeMotionCancel();
4080 secondWindow->consumeMotionDown();
4081
4082 // Send up event to the second window
4083 NotifyMotionArgs upMotionArgs =
4084 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4085 ADISPLAY_ID_DEFAULT);
4086 mDispatcher->notifyMotion(&upMotionArgs);
4087 // The first window gets no events and the second+spy get up
4088 firstWindow->assertNoEvents();
4089 spyWindow->consumeMotionUp();
4090 secondWindow->consumeMotionUp();
4091}
4092
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004093TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004094 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004095
4096 PointF touchPoint = {10, 10};
4097
4098 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004099 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004100 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4101 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004102 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004103 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004104 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4105 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004106 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004107
4108 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004109 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004110
4111 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004112 NotifyMotionArgs downMotionArgs =
4113 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4114 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004115 mDispatcher->notifyMotion(&downMotionArgs);
4116 // Only the first window should get the down event
4117 firstWindow->consumeMotionDown();
4118 secondWindow->assertNoEvents();
4119
4120 // Send pointer down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004121 NotifyMotionArgs pointerDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004122 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004123 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004124 mDispatcher->notifyMotion(&pointerDownMotionArgs);
4125 // Only the first window should get the pointer down event
4126 firstWindow->consumeMotionPointerDown(1);
4127 secondWindow->assertNoEvents();
4128
4129 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004130 TransferFunction f = GetParam();
4131 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4132 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004133 // The first window gets cancel and the second gets down and pointer down
4134 firstWindow->consumeMotionCancel();
4135 secondWindow->consumeMotionDown();
4136 secondWindow->consumeMotionPointerDown(1);
4137
4138 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004139 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004140 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004141 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004142 mDispatcher->notifyMotion(&pointerUpMotionArgs);
4143 // The first window gets nothing and the second gets pointer up
4144 firstWindow->assertNoEvents();
4145 secondWindow->consumeMotionPointerUp(1);
4146
4147 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004148 NotifyMotionArgs upMotionArgs =
4149 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4150 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004151 mDispatcher->notifyMotion(&upMotionArgs);
4152 // The first window gets nothing and the second gets up
4153 firstWindow->assertNoEvents();
4154 secondWindow->consumeMotionUp();
4155}
4156
Arthur Hungc539dbb2022-12-08 07:45:36 +00004157TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4158 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4159
4160 // Create a couple of windows
4161 sp<FakeWindowHandle> firstWindow =
4162 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4163 ADISPLAY_ID_DEFAULT);
4164 firstWindow->setDupTouchToWallpaper(true);
4165 sp<FakeWindowHandle> secondWindow =
4166 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4167 ADISPLAY_ID_DEFAULT);
4168 secondWindow->setDupTouchToWallpaper(true);
4169
4170 sp<FakeWindowHandle> wallpaper1 =
4171 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4172 wallpaper1->setIsWallpaper(true);
4173
4174 sp<FakeWindowHandle> wallpaper2 =
4175 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4176 wallpaper2->setIsWallpaper(true);
4177 // Add the windows to the dispatcher
4178 mDispatcher->setInputWindows(
4179 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4180
4181 // Send down to the first window
4182 NotifyMotionArgs downMotionArgs =
4183 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4184 ADISPLAY_ID_DEFAULT);
4185 mDispatcher->notifyMotion(&downMotionArgs);
4186
4187 // Only the first window should get the down event
4188 firstWindow->consumeMotionDown();
4189 secondWindow->assertNoEvents();
4190 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4191 wallpaper2->assertNoEvents();
4192
4193 // Transfer touch focus to the second window
4194 TransferFunction f = GetParam();
4195 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4196 ASSERT_TRUE(success);
4197
4198 // The first window gets cancel and the second gets down
4199 firstWindow->consumeMotionCancel();
4200 secondWindow->consumeMotionDown();
4201 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4202 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4203
4204 // Send up event to the second window
4205 NotifyMotionArgs upMotionArgs =
4206 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4207 ADISPLAY_ID_DEFAULT);
4208 mDispatcher->notifyMotion(&upMotionArgs);
4209 // The first window gets no events and the second gets up
4210 firstWindow->assertNoEvents();
4211 secondWindow->consumeMotionUp();
4212 wallpaper1->assertNoEvents();
4213 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4214}
4215
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004216// For the cases of single pointer touch and two pointers non-split touch, the api's
4217// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4218// for the case where there are multiple pointers split across several windows.
4219INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4220 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004221 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4222 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004223 return dispatcher->transferTouch(destChannelToken,
4224 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004225 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004226 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4227 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004228 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004229 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004230 }));
4231
Svet Ganov5d3bc372020-01-26 23:11:07 -08004232TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004233 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004234
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004235 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004236 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4237 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004238 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004239
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004240 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004241 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4242 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004243 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004244
4245 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004246 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004247
4248 PointF pointInFirst = {300, 200};
4249 PointF pointInSecond = {300, 600};
4250
4251 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004252 NotifyMotionArgs firstDownMotionArgs =
4253 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4254 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004255 mDispatcher->notifyMotion(&firstDownMotionArgs);
4256 // Only the first window should get the down event
4257 firstWindow->consumeMotionDown();
4258 secondWindow->assertNoEvents();
4259
4260 // Send down to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004261 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004262 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004263 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004264 mDispatcher->notifyMotion(&secondDownMotionArgs);
4265 // The first window gets a move and the second a down
4266 firstWindow->consumeMotionMove();
4267 secondWindow->consumeMotionDown();
4268
4269 // Transfer touch focus to the second window
4270 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4271 // The first window gets cancel and the new gets pointer down (it already saw down)
4272 firstWindow->consumeMotionCancel();
4273 secondWindow->consumeMotionPointerDown(1);
4274
4275 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004276 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004277 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004278 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004279 mDispatcher->notifyMotion(&pointerUpMotionArgs);
4280 // The first window gets nothing and the second gets pointer up
4281 firstWindow->assertNoEvents();
4282 secondWindow->consumeMotionPointerUp(1);
4283
4284 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004285 NotifyMotionArgs upMotionArgs =
4286 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4287 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004288 mDispatcher->notifyMotion(&upMotionArgs);
4289 // The first window gets nothing and the second gets up
4290 firstWindow->assertNoEvents();
4291 secondWindow->consumeMotionUp();
4292}
4293
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004294// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4295// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4296// touch is not supported, so the touch should continue on those windows and the transferred-to
4297// window should get nothing.
4298TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4299 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4300
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004301 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004302 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4303 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004304 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004305
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004306 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004307 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4308 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004309 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004310
4311 // Add the windows to the dispatcher
4312 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4313
4314 PointF pointInFirst = {300, 200};
4315 PointF pointInSecond = {300, 600};
4316
4317 // Send down to the first window
4318 NotifyMotionArgs firstDownMotionArgs =
4319 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4320 ADISPLAY_ID_DEFAULT, {pointInFirst});
4321 mDispatcher->notifyMotion(&firstDownMotionArgs);
4322 // Only the first window should get the down event
4323 firstWindow->consumeMotionDown();
4324 secondWindow->assertNoEvents();
4325
4326 // Send down to the second window
4327 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004328 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004329 {pointInFirst, pointInSecond});
4330 mDispatcher->notifyMotion(&secondDownMotionArgs);
4331 // The first window gets a move and the second a down
4332 firstWindow->consumeMotionMove();
4333 secondWindow->consumeMotionDown();
4334
4335 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004336 const bool transferred =
4337 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004338 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4339 ASSERT_FALSE(transferred);
4340 firstWindow->assertNoEvents();
4341 secondWindow->assertNoEvents();
4342
4343 // The rest of the dispatch should proceed as normal
4344 // Send pointer up to the second window
4345 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004346 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004347 {pointInFirst, pointInSecond});
4348 mDispatcher->notifyMotion(&pointerUpMotionArgs);
4349 // The first window gets MOVE and the second gets pointer up
4350 firstWindow->consumeMotionMove();
4351 secondWindow->consumeMotionUp();
4352
4353 // Send up event to the first window
4354 NotifyMotionArgs upMotionArgs =
4355 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4356 ADISPLAY_ID_DEFAULT);
4357 mDispatcher->notifyMotion(&upMotionArgs);
4358 // The first window gets nothing and the second gets up
4359 firstWindow->consumeMotionUp();
4360 secondWindow->assertNoEvents();
4361}
4362
Arthur Hungabbb9d82021-09-01 14:52:30 +00004363// This case will create two windows and one mirrored window on the default display and mirror
4364// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4365// the windows info of second display before default display.
4366TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4367 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4368 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004369 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004370 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004371 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004372 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004373 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004374
4375 sp<FakeWindowHandle> mirrorWindowInPrimary =
4376 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4377 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004378
4379 sp<FakeWindowHandle> firstWindowInSecondary =
4380 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4381 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004382
4383 sp<FakeWindowHandle> secondWindowInSecondary =
4384 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4385 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004386
4387 // Update window info, let it find window handle of second display first.
4388 mDispatcher->setInputWindows(
4389 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4390 {ADISPLAY_ID_DEFAULT,
4391 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4392
4393 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4394 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4395 {50, 50}))
4396 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4397
4398 // Window should receive motion event.
4399 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4400
4401 // Transfer touch focus
4402 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4403 secondWindowInPrimary->getToken()));
4404 // The first window gets cancel.
4405 firstWindowInPrimary->consumeMotionCancel();
4406 secondWindowInPrimary->consumeMotionDown();
4407
4408 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4409 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4410 ADISPLAY_ID_DEFAULT, {150, 50}))
4411 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4412 firstWindowInPrimary->assertNoEvents();
4413 secondWindowInPrimary->consumeMotionMove();
4414
4415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4416 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4417 {150, 50}))
4418 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4419 firstWindowInPrimary->assertNoEvents();
4420 secondWindowInPrimary->consumeMotionUp();
4421}
4422
4423// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4424// 'transferTouch' api.
4425TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4426 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4427 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004428 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004429 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004430 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004431 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004432 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004433
4434 sp<FakeWindowHandle> mirrorWindowInPrimary =
4435 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4436 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004437
4438 sp<FakeWindowHandle> firstWindowInSecondary =
4439 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4440 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004441
4442 sp<FakeWindowHandle> secondWindowInSecondary =
4443 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4444 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004445
4446 // Update window info, let it find window handle of second display first.
4447 mDispatcher->setInputWindows(
4448 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4449 {ADISPLAY_ID_DEFAULT,
4450 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4451
4452 // Touch on second display.
4453 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4454 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4455 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4456
4457 // Window should receive motion event.
4458 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4459
4460 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004461 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004462
4463 // The first window gets cancel.
4464 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4465 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4466
4467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4468 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4469 SECOND_DISPLAY_ID, {150, 50}))
4470 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4471 firstWindowInPrimary->assertNoEvents();
4472 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4473
4474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4475 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4476 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4477 firstWindowInPrimary->assertNoEvents();
4478 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4479}
4480
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004481TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004482 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004483 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4484 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004485
Vishnu Nair47074b82020-08-14 11:54:47 -07004486 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004487 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004488 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004489
4490 window->consumeFocusEvent(true);
4491
4492 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4493 mDispatcher->notifyKey(&keyArgs);
4494
4495 // Window should receive key down event.
4496 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4497}
4498
4499TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004500 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004501 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4502 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004503
Arthur Hung72d8dc32020-03-28 00:48:39 +00004504 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004505
4506 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4507 mDispatcher->notifyKey(&keyArgs);
4508 mDispatcher->waitForIdle();
4509
4510 window->assertNoEvents();
4511}
4512
4513// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4514TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004515 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004516 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4517 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004518
Arthur Hung72d8dc32020-03-28 00:48:39 +00004519 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004520
4521 // Send key
4522 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4523 mDispatcher->notifyKey(&keyArgs);
4524 // Send motion
4525 NotifyMotionArgs motionArgs =
4526 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4527 ADISPLAY_ID_DEFAULT);
4528 mDispatcher->notifyMotion(&motionArgs);
4529
4530 // Window should receive only the motion event
4531 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4532 window->assertNoEvents(); // Key event or focus event will not be received
4533}
4534
arthurhungea3f4fc2020-12-21 23:18:53 +08004535TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4536 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4537
arthurhungea3f4fc2020-12-21 23:18:53 +08004538 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004539 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4540 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004541 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004542
arthurhungea3f4fc2020-12-21 23:18:53 +08004543 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004544 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4545 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004546 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004547
4548 // Add the windows to the dispatcher
4549 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4550
4551 PointF pointInFirst = {300, 200};
4552 PointF pointInSecond = {300, 600};
4553
4554 // Send down to the first window
4555 NotifyMotionArgs firstDownMotionArgs =
4556 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4557 ADISPLAY_ID_DEFAULT, {pointInFirst});
4558 mDispatcher->notifyMotion(&firstDownMotionArgs);
4559 // Only the first window should get the down event
4560 firstWindow->consumeMotionDown();
4561 secondWindow->assertNoEvents();
4562
4563 // Send down to the second window
4564 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004565 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004566 {pointInFirst, pointInSecond});
4567 mDispatcher->notifyMotion(&secondDownMotionArgs);
4568 // The first window gets a move and the second a down
4569 firstWindow->consumeMotionMove();
4570 secondWindow->consumeMotionDown();
4571
4572 // Send pointer cancel to the second window
4573 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004574 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004575 {pointInFirst, pointInSecond});
4576 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
4577 mDispatcher->notifyMotion(&pointerUpMotionArgs);
4578 // The first window gets move and the second gets cancel.
4579 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4580 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4581
4582 // Send up event.
4583 NotifyMotionArgs upMotionArgs =
4584 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4585 ADISPLAY_ID_DEFAULT);
4586 mDispatcher->notifyMotion(&upMotionArgs);
4587 // The first window gets up and the second gets nothing.
4588 firstWindow->consumeMotionUp();
4589 secondWindow->assertNoEvents();
4590}
4591
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004592TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4593 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4594
4595 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004596 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004597 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4598 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4599 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4600 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4601
Harry Cutts33476232023-01-30 19:57:29 +00004602 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004603 window->assertNoEvents();
4604 mDispatcher->waitForIdle();
4605}
4606
chaviwd1c23182019-12-20 18:44:56 -08004607class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004608public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004609 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004610 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004611 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004612 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004613 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004614 }
4615
chaviwd1c23182019-12-20 18:44:56 -08004616 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4617
4618 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
4619 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
4620 expectedDisplayId, expectedFlags);
4621 }
4622
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004623 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4624
4625 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4626
chaviwd1c23182019-12-20 18:44:56 -08004627 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
4628 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
4629 expectedDisplayId, expectedFlags);
4630 }
4631
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004632 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
4633 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE,
4634 expectedDisplayId, expectedFlags);
4635 }
4636
chaviwd1c23182019-12-20 18:44:56 -08004637 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
4638 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
4639 expectedDisplayId, expectedFlags);
4640 }
4641
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004642 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004643 mInputReceiver->consumeMotionEvent(
4644 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4645 WithDisplayId(expectedDisplayId),
4646 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004647 }
4648
Arthur Hungfbfa5722021-11-16 02:45:54 +00004649 void consumeMotionPointerDown(int32_t pointerIdx) {
4650 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4651 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
4652 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004653 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004654 }
4655
Evan Rosky84f07f02021-04-16 10:42:42 -07004656 MotionEvent* consumeMotion() {
4657 InputEvent* event = mInputReceiver->consume();
4658 if (!event) {
4659 ADD_FAILURE() << "No event was produced";
4660 return nullptr;
4661 }
4662 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
4663 ADD_FAILURE() << "Received event of type " << event->getType() << " instead of motion";
4664 return nullptr;
4665 }
4666 return static_cast<MotionEvent*>(event);
4667 }
4668
chaviwd1c23182019-12-20 18:44:56 -08004669 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4670
4671private:
4672 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004673};
4674
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004675using InputDispatcherMonitorTest = InputDispatcherTest;
4676
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004677/**
4678 * Two entities that receive touch: A window, and a global monitor.
4679 * The touch goes to the window, and then the window disappears.
4680 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4681 * for the monitor, as well.
4682 * 1. foregroundWindow
4683 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4684 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004685TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004686 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4687 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004688 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004689
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004690 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004691
4692 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4693 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4694 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4695 {100, 200}))
4696 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4697
4698 // Both the foreground window and the global monitor should receive the touch down
4699 window->consumeMotionDown();
4700 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4701
4702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4703 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4704 ADISPLAY_ID_DEFAULT, {110, 200}))
4705 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4706
4707 window->consumeMotionMove();
4708 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
4709
4710 // Now the foreground window goes away
4711 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
4712 window->consumeMotionCancel();
4713 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
4714
4715 // If more events come in, there will be no more foreground window to send them to. This will
4716 // cause a cancel for the monitor, as well.
4717 ASSERT_EQ(InputEventInjectionResult::FAILED,
4718 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4719 ADISPLAY_ID_DEFAULT, {120, 200}))
4720 << "Injection should fail because the window was removed";
4721 window->assertNoEvents();
4722 // Global monitor now gets the cancel
4723 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
4724}
4725
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004726TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07004727 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004728 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4729 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004730 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00004731
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004732 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004733
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004734 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00004735 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004736 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00004737 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08004738 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004739}
4740
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004741TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
4742 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004743
Chris Yea209fde2020-07-22 13:54:51 -07004744 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004745 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4746 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004747 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00004748
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004749 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00004750 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004751 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08004752 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004753 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004754
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004755 // Pilfer pointers from the monitor.
4756 // This should not do anything and the window should continue to receive events.
4757 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00004758
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004760 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4761 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004762 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004763
4764 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
4765 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004766}
4767
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004768TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07004769 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004770 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4771 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07004772 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4773 window->setWindowOffset(20, 40);
4774 window->setWindowTransform(0, 1, -1, 0);
4775
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004776 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07004777
4778 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4779 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
4780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4781 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4782 MotionEvent* event = monitor.consumeMotion();
4783 // Even though window has transform, gesture monitor must not.
4784 ASSERT_EQ(ui::Transform(), event->getTransform());
4785}
4786
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004787TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00004788 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004789 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00004790
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004791 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00004792 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004793 << "Injection should fail if there is a monitor, but no touchable window";
4794 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00004795}
4796
chaviw81e2bb92019-12-18 15:03:51 -08004797TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004798 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004799 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4800 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08004801
Arthur Hung72d8dc32020-03-28 00:48:39 +00004802 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08004803
4804 NotifyMotionArgs motionArgs =
4805 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4806 ADISPLAY_ID_DEFAULT);
4807
4808 mDispatcher->notifyMotion(&motionArgs);
4809 // Window should receive motion down event.
4810 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4811
4812 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08004813 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08004814 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
4815 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
4816 motionArgs.pointerCoords[0].getX() - 10);
4817
4818 mDispatcher->notifyMotion(&motionArgs);
4819 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004820 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08004821}
4822
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004823/**
4824 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
4825 * the device default right away. In the test scenario, we check both the default value,
4826 * and the action of enabling / disabling.
4827 */
4828TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07004829 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004830 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4831 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08004832 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004833
4834 // Set focused application.
4835 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07004836 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004837
4838 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00004839 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004840 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00004841 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004842
4843 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07004844 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004845 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00004846 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004847
4848 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08004849 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00004850 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00004851 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07004852 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004853 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004854 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00004855 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004856
4857 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07004858 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004859 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00004860 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004861
4862 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08004863 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00004864 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00004865 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07004866 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004867 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004868 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00004869 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004870
4871 window->assertNoEvents();
4872}
4873
Gang Wange9087892020-01-07 12:17:14 -05004874TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004875 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004876 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4877 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05004878
4879 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07004880 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05004881
Arthur Hung72d8dc32020-03-28 00:48:39 +00004882 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004883 setFocusedWindow(window);
4884
Harry Cutts33476232023-01-30 19:57:29 +00004885 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05004886
4887 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
4888 mDispatcher->notifyKey(&keyArgs);
4889
4890 InputEvent* event = window->consume();
4891 ASSERT_NE(event, nullptr);
4892
4893 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
4894 ASSERT_NE(verified, nullptr);
4895 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
4896
4897 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
4898 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
4899 ASSERT_EQ(keyArgs.source, verified->source);
4900 ASSERT_EQ(keyArgs.displayId, verified->displayId);
4901
4902 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
4903
4904 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05004905 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08004906 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05004907 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
4908 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
4909 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
4910 ASSERT_EQ(0, verifiedKey.repeatCount);
4911}
4912
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004913TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004914 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004915 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4916 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004917
4918 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4919
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07004920 ui::Transform transform;
4921 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
4922
4923 gui::DisplayInfo displayInfo;
4924 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
4925 displayInfo.transform = transform;
4926
4927 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004928
4929 NotifyMotionArgs motionArgs =
4930 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4931 ADISPLAY_ID_DEFAULT);
4932 mDispatcher->notifyMotion(&motionArgs);
4933
4934 InputEvent* event = window->consume();
4935 ASSERT_NE(event, nullptr);
4936
4937 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
4938 ASSERT_NE(verified, nullptr);
4939 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
4940
4941 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
4942 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
4943 EXPECT_EQ(motionArgs.source, verified->source);
4944 EXPECT_EQ(motionArgs.displayId, verified->displayId);
4945
4946 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
4947
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07004948 const vec2 rawXY =
4949 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
4950 motionArgs.pointerCoords[0].getXYValue());
4951 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
4952 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004953 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004954 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08004955 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004956 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
4957 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
4958}
4959
chaviw09c8d2d2020-08-24 15:48:26 -07004960/**
4961 * Ensure that separate calls to sign the same data are generating the same key.
4962 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
4963 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
4964 * tests.
4965 */
4966TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
4967 KeyEvent event = getTestKeyEvent();
4968 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
4969
4970 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
4971 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
4972 ASSERT_EQ(hmac1, hmac2);
4973}
4974
4975/**
4976 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
4977 */
4978TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
4979 KeyEvent event = getTestKeyEvent();
4980 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
4981 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
4982
4983 verifiedEvent.deviceId += 1;
4984 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
4985
4986 verifiedEvent.source += 1;
4987 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
4988
4989 verifiedEvent.eventTimeNanos += 1;
4990 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
4991
4992 verifiedEvent.displayId += 1;
4993 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
4994
4995 verifiedEvent.action += 1;
4996 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
4997
4998 verifiedEvent.downTimeNanos += 1;
4999 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5000
5001 verifiedEvent.flags += 1;
5002 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5003
5004 verifiedEvent.keyCode += 1;
5005 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5006
5007 verifiedEvent.scanCode += 1;
5008 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5009
5010 verifiedEvent.metaState += 1;
5011 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5012
5013 verifiedEvent.repeatCount += 1;
5014 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5015}
5016
Vishnu Nair958da932020-08-21 17:12:37 -07005017TEST_F(InputDispatcherTest, SetFocusedWindow) {
5018 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5019 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005020 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005021 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005022 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005023 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5024
5025 // Top window is also focusable but is not granted focus.
5026 windowTop->setFocusable(true);
5027 windowSecond->setFocusable(true);
5028 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5029 setFocusedWindow(windowSecond);
5030
5031 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5033 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005034
5035 // Focused window should receive event.
5036 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5037 windowTop->assertNoEvents();
5038}
5039
5040TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5041 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5042 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005043 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005044 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5045
5046 window->setFocusable(true);
5047 // Release channel for window is no longer valid.
5048 window->releaseChannel();
5049 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5050 setFocusedWindow(window);
5051
5052 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005053 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5054 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005055
5056 // window channel is invalid, so it should not receive any input event.
5057 window->assertNoEvents();
5058}
5059
5060TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5061 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5062 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005063 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005064 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005065 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5066
Vishnu Nair958da932020-08-21 17:12:37 -07005067 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5068 setFocusedWindow(window);
5069
5070 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005071 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5072 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005073
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005074 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005075 window->assertNoEvents();
5076}
5077
5078TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5079 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5080 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005081 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005082 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005083 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005084 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5085
5086 windowTop->setFocusable(true);
5087 windowSecond->setFocusable(true);
5088 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5089 setFocusedWindow(windowTop);
5090 windowTop->consumeFocusEvent(true);
5091
5092 setFocusedWindow(windowSecond, windowTop);
5093 windowSecond->consumeFocusEvent(true);
5094 windowTop->consumeFocusEvent(false);
5095
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005096 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5097 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005098
5099 // Focused window should receive event.
5100 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5101}
5102
5103TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
5104 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5105 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005106 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005107 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005108 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005109 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5110
5111 windowTop->setFocusable(true);
5112 windowSecond->setFocusable(true);
5113 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5114 setFocusedWindow(windowSecond, windowTop);
5115
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005116 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5117 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005118
5119 // Event should be dropped.
5120 windowTop->assertNoEvents();
5121 windowSecond->assertNoEvents();
5122}
5123
5124TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5125 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5126 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005127 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005128 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005129 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5130 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005131 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5132
5133 window->setFocusable(true);
5134 previousFocusedWindow->setFocusable(true);
5135 window->setVisible(false);
5136 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5137 setFocusedWindow(previousFocusedWindow);
5138 previousFocusedWindow->consumeFocusEvent(true);
5139
5140 // Requesting focus on invisible window takes focus from currently focused window.
5141 setFocusedWindow(window);
5142 previousFocusedWindow->consumeFocusEvent(false);
5143
5144 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005145 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005146 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5147 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005148
5149 // Window does not get focus event or key down.
5150 window->assertNoEvents();
5151
5152 // Window becomes visible.
5153 window->setVisible(true);
5154 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5155
5156 // Window receives focus event.
5157 window->consumeFocusEvent(true);
5158 // Focused window receives key down.
5159 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5160}
5161
Vishnu Nair599f1412021-06-21 10:39:58 -07005162TEST_F(InputDispatcherTest, DisplayRemoved) {
5163 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5164 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005165 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005166 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5167
5168 // window is granted focus.
5169 window->setFocusable(true);
5170 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5171 setFocusedWindow(window);
5172 window->consumeFocusEvent(true);
5173
5174 // When a display is removed window loses focus.
5175 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5176 window->consumeFocusEvent(false);
5177}
5178
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005179/**
5180 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5181 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5182 * of the 'slipperyEnterWindow'.
5183 *
5184 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5185 * a way so that the touched location is no longer covered by the top window.
5186 *
5187 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5188 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5189 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5190 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5191 * with ACTION_DOWN).
5192 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5193 * window moved itself away from the touched location and had Flag::SLIPPERY.
5194 *
5195 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5196 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5197 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5198 *
5199 * In this test, we ensure that the event received by the bottom window has
5200 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5201 */
5202TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00005203 constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
5204 constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005205
5206 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5207 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5208
5209 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005210 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005211 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005212 // Make sure this one overlaps the bottom window
5213 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5214 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5215 // one. Windows with the same owner are not considered to be occluding each other.
5216 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5217
5218 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005219 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005220 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5221
5222 mDispatcher->setInputWindows(
5223 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5224
5225 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
5226 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5227 ADISPLAY_ID_DEFAULT, {{50, 50}});
5228 mDispatcher->notifyMotion(&args);
5229 slipperyExitWindow->consumeMotionDown();
5230 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5231 mDispatcher->setInputWindows(
5232 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5233
5234 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5235 ADISPLAY_ID_DEFAULT, {{51, 51}});
5236 mDispatcher->notifyMotion(&args);
5237
5238 slipperyExitWindow->consumeMotionCancel();
5239
5240 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5241 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5242}
5243
Garfield Tan1c7bc862020-01-28 13:24:04 -08005244class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5245protected:
5246 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5247 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5248
Chris Yea209fde2020-07-22 13:54:51 -07005249 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005250 sp<FakeWindowHandle> mWindow;
5251
5252 virtual void SetUp() override {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005253 mFakePolicy = sp<FakeInputDispatcherPolicy>::make();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005254 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005255 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005256 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
5257 ASSERT_EQ(OK, mDispatcher->start());
5258
5259 setUpWindow();
5260 }
5261
5262 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005263 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005264 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005265
Vishnu Nair47074b82020-08-14 11:54:47 -07005266 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005267 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005268 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005269 mWindow->consumeFocusEvent(true);
5270 }
5271
Chris Ye2ad95392020-09-01 13:44:44 -07005272 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005273 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005274 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005275 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
5276 mDispatcher->notifyKey(&keyArgs);
5277
5278 // Window should receive key down event.
5279 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5280 }
5281
5282 void expectKeyRepeatOnce(int32_t repeatCount) {
5283 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5284 InputEvent* repeatEvent = mWindow->consume();
5285 ASSERT_NE(nullptr, repeatEvent);
5286
5287 uint32_t eventType = repeatEvent->getType();
5288 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
5289
5290 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5291 uint32_t eventAction = repeatKeyEvent->getAction();
5292 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5293 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5294 }
5295
Chris Ye2ad95392020-09-01 13:44:44 -07005296 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005297 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005298 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005299 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
5300 mDispatcher->notifyKey(&keyArgs);
5301
5302 // Window should receive key down event.
5303 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005304 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005305 }
5306};
5307
5308TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005309 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005310 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5311 expectKeyRepeatOnce(repeatCount);
5312 }
5313}
5314
5315TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005316 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005317 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5318 expectKeyRepeatOnce(repeatCount);
5319 }
Harry Cutts33476232023-01-30 19:57:29 +00005320 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005321 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005322 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5323 expectKeyRepeatOnce(repeatCount);
5324 }
5325}
5326
5327TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005328 sendAndConsumeKeyDown(/*deviceId=*/1);
5329 expectKeyRepeatOnce(/*repeatCount=*/1);
5330 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005331 mWindow->assertNoEvents();
5332}
5333
5334TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005335 sendAndConsumeKeyDown(/*deviceId=*/1);
5336 expectKeyRepeatOnce(/*repeatCount=*/1);
5337 sendAndConsumeKeyDown(/*deviceId=*/2);
5338 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005339 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005340 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005341 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005342 expectKeyRepeatOnce(/*repeatCount=*/2);
5343 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005344 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005345 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005346 mWindow->assertNoEvents();
5347}
5348
5349TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005350 sendAndConsumeKeyDown(/*deviceId=*/1);
5351 expectKeyRepeatOnce(/*repeatCount=*/1);
5352 sendAndConsumeKeyDown(/*deviceId=*/2);
5353 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005354 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005355 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005356 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005357 mWindow->assertNoEvents();
5358}
5359
liushenxiang42232912021-05-21 20:24:09 +08005360TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5361 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005362 expectKeyRepeatOnce(/*repeatCount=*/1);
5363 NotifyDeviceResetArgs args(/*id=*/10, /*eventTime=*/20, DEVICE_ID);
liushenxiang42232912021-05-21 20:24:09 +08005364 mDispatcher->notifyDeviceReset(&args);
5365 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5366 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5367 mWindow->assertNoEvents();
5368}
5369
Garfield Tan1c7bc862020-01-28 13:24:04 -08005370TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Harry Cutts33476232023-01-30 19:57:29 +00005371 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005372 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5373 InputEvent* repeatEvent = mWindow->consume();
5374 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5375 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5376 IdGenerator::getSource(repeatEvent->getId()));
5377 }
5378}
5379
5380TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Harry Cutts33476232023-01-30 19:57:29 +00005381 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005382
5383 std::unordered_set<int32_t> idSet;
5384 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5385 InputEvent* repeatEvent = mWindow->consume();
5386 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5387 int32_t id = repeatEvent->getId();
5388 EXPECT_EQ(idSet.end(), idSet.find(id));
5389 idSet.insert(id);
5390 }
5391}
5392
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005393/* Test InputDispatcher for MultiDisplay */
5394class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5395public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005396 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005397 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005398
Chris Yea209fde2020-07-22 13:54:51 -07005399 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005400 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005401 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005402
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005403 // Set focus window for primary display, but focused display would be second one.
5404 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005405 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005406 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005407 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005408 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005409
Chris Yea209fde2020-07-22 13:54:51 -07005410 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005411 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005412 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005413 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005414 // Set focus display to second one.
5415 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5416 // Set focus window for second display.
5417 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005418 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005419 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005420 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005421 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005422 }
5423
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005424 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005425 InputDispatcherTest::TearDown();
5426
Chris Yea209fde2020-07-22 13:54:51 -07005427 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005428 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005429 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005430 windowInSecondary.clear();
5431 }
5432
5433protected:
Chris Yea209fde2020-07-22 13:54:51 -07005434 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005435 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005436 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005437 sp<FakeWindowHandle> windowInSecondary;
5438};
5439
5440TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5441 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5443 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5444 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005445 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005446 windowInSecondary->assertNoEvents();
5447
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005448 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005449 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5450 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5451 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005452 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005453 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005454}
5455
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005456TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005457 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5459 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005460 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005461 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005462 windowInSecondary->assertNoEvents();
5463
5464 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005466 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005467 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005468 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005469
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005470 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005471 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005472
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005473 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005474 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
5475 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005476
5477 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005478 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005479 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005480 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005481 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005482 windowInSecondary->assertNoEvents();
5483}
5484
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005485// Test per-display input monitors for motion event.
5486TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005487 FakeMonitorReceiver monitorInPrimary =
5488 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5489 FakeMonitorReceiver monitorInSecondary =
5490 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005491
5492 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005493 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5494 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5495 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005496 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005497 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005498 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005499 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005500
5501 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005502 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5503 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5504 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005505 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005506 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005507 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005508 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005509
5510 // Test inject a non-pointer motion event.
5511 // If specific a display, it will dispatch to the focused window of particular display,
5512 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5514 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5515 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005516 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005517 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005518 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005519 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005520}
5521
5522// Test per-display input monitors for key event.
5523TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005524 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005525 FakeMonitorReceiver monitorInPrimary =
5526 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5527 FakeMonitorReceiver monitorInSecondary =
5528 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005529
5530 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005531 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5532 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005533 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005534 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005535 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005536 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005537}
5538
Vishnu Nair958da932020-08-21 17:12:37 -07005539TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
5540 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005541 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005542 secondWindowInPrimary->setFocusable(true);
5543 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
5544 setFocusedWindow(secondWindowInPrimary);
5545 windowInPrimary->consumeFocusEvent(false);
5546 secondWindowInPrimary->consumeFocusEvent(true);
5547
5548 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005549 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
5550 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005551 windowInPrimary->assertNoEvents();
5552 windowInSecondary->assertNoEvents();
5553 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5554}
5555
Arthur Hungdfd528e2021-12-08 13:23:04 +00005556TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
5557 FakeMonitorReceiver monitorInPrimary =
5558 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5559 FakeMonitorReceiver monitorInSecondary =
5560 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
5561
5562 // Test touch down on primary display.
5563 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5564 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5565 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5566 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5567 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5568
5569 // Test touch down on second display.
5570 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5571 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5572 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5573 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
5574 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
5575
5576 // Trigger cancel touch.
5577 mDispatcher->cancelCurrentTouch();
5578 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5579 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5580 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
5581 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
5582
5583 // Test inject a move motion event, no window/monitor should receive the event.
5584 ASSERT_EQ(InputEventInjectionResult::FAILED,
5585 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5586 ADISPLAY_ID_DEFAULT, {110, 200}))
5587 << "Inject motion event should return InputEventInjectionResult::FAILED";
5588 windowInPrimary->assertNoEvents();
5589 monitorInPrimary.assertNoEvents();
5590
5591 ASSERT_EQ(InputEventInjectionResult::FAILED,
5592 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5593 SECOND_DISPLAY_ID, {110, 200}))
5594 << "Inject motion event should return InputEventInjectionResult::FAILED";
5595 windowInSecondary->assertNoEvents();
5596 monitorInSecondary.assertNoEvents();
5597}
5598
Jackal Guof9696682018-10-05 12:23:23 +08005599class InputFilterTest : public InputDispatcherTest {
5600protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005601 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
5602 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08005603 NotifyMotionArgs motionArgs;
5604
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005605 motionArgs =
5606 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08005607 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005608 motionArgs =
5609 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08005610 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005611 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005612 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005613 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
5614 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08005615 } else {
5616 mFakePolicy->assertFilterInputEventWasNotCalled();
5617 }
5618 }
5619
5620 void testNotifyKey(bool expectToBeFiltered) {
5621 NotifyKeyArgs keyArgs;
5622
5623 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5624 mDispatcher->notifyKey(&keyArgs);
5625 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
5626 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005627 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005628
5629 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08005630 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08005631 } else {
5632 mFakePolicy->assertFilterInputEventWasNotCalled();
5633 }
5634 }
5635};
5636
5637// Test InputFilter for MotionEvent
5638TEST_F(InputFilterTest, MotionEvent_InputFilter) {
5639 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
5640 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5641 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5642
5643 // Enable InputFilter
5644 mDispatcher->setInputFilterEnabled(true);
5645 // Test touch on both primary and second display, and check if both events are filtered.
5646 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
5647 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
5648
5649 // Disable InputFilter
5650 mDispatcher->setInputFilterEnabled(false);
5651 // Test touch on both primary and second display, and check if both events aren't filtered.
5652 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5653 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5654}
5655
5656// Test InputFilter for KeyEvent
5657TEST_F(InputFilterTest, KeyEvent_InputFilter) {
5658 // Since the InputFilter is disabled by default, check if key event aren't filtered.
5659 testNotifyKey(/*expectToBeFiltered*/ false);
5660
5661 // Enable InputFilter
5662 mDispatcher->setInputFilterEnabled(true);
5663 // Send a key event, and check if it is filtered.
5664 testNotifyKey(/*expectToBeFiltered*/ true);
5665
5666 // Disable InputFilter
5667 mDispatcher->setInputFilterEnabled(false);
5668 // Send a key event, and check if it isn't filtered.
5669 testNotifyKey(/*expectToBeFiltered*/ false);
5670}
5671
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005672// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
5673// logical display coordinate space.
5674TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
5675 ui::Transform firstDisplayTransform;
5676 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5677 ui::Transform secondDisplayTransform;
5678 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
5679
5680 std::vector<gui::DisplayInfo> displayInfos(2);
5681 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
5682 displayInfos[0].transform = firstDisplayTransform;
5683 displayInfos[1].displayId = SECOND_DISPLAY_ID;
5684 displayInfos[1].transform = secondDisplayTransform;
5685
5686 mDispatcher->onWindowInfosChanged({}, displayInfos);
5687
5688 // Enable InputFilter
5689 mDispatcher->setInputFilterEnabled(true);
5690
5691 // Ensure the correct transforms are used for the displays.
5692 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
5693 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
5694}
5695
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005696class InputFilterInjectionPolicyTest : public InputDispatcherTest {
5697protected:
5698 virtual void SetUp() override {
5699 InputDispatcherTest::SetUp();
5700
5701 /**
5702 * We don't need to enable input filter to test the injected event policy, but we enabled it
5703 * here to make the tests more realistic, since this policy only matters when inputfilter is
5704 * on.
5705 */
5706 mDispatcher->setInputFilterEnabled(true);
5707
5708 std::shared_ptr<InputApplicationHandle> application =
5709 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005710 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
5711 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005712
5713 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5714 mWindow->setFocusable(true);
5715 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5716 setFocusedWindow(mWindow);
5717 mWindow->consumeFocusEvent(true);
5718 }
5719
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005720 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
5721 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005722 KeyEvent event;
5723
5724 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5725 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
5726 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00005727 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005728 const int32_t additionalPolicyFlags =
5729 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
5730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005731 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005732 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
5733 policyFlags | additionalPolicyFlags));
5734
5735 InputEvent* received = mWindow->consume();
5736 ASSERT_NE(nullptr, received);
5737 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005738 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_KEY);
5739 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
5740 ASSERT_EQ(flags, keyEvent.getFlags());
5741 }
5742
5743 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
5744 int32_t flags) {
5745 MotionEvent event;
5746 PointerProperties pointerProperties[1];
5747 PointerCoords pointerCoords[1];
5748 pointerProperties[0].clear();
5749 pointerProperties[0].id = 0;
5750 pointerCoords[0].clear();
5751 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
5752 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
5753
5754 ui::Transform identityTransform;
5755 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5756 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
5757 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
5758 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
5759 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07005760 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07005761 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005762 /*pointerCount*/ 1, pointerProperties, pointerCoords);
5763
5764 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
5765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005766 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005767 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
5768 policyFlags | additionalPolicyFlags));
5769
5770 InputEvent* received = mWindow->consume();
5771 ASSERT_NE(nullptr, received);
5772 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
5773 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_MOTION);
5774 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
5775 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005776 }
5777
5778private:
5779 sp<FakeWindowHandle> mWindow;
5780};
5781
5782TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005783 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
5784 // filter. Without it, the event will no different from a regularly injected event, and the
5785 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00005786 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
5787 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005788}
5789
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005790TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005791 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00005792 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005793 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
5794}
5795
5796TEST_F(InputFilterInjectionPolicyTest,
5797 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
5798 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00005799 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005800 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005801}
5802
5803TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00005804 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
5805 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005806}
5807
chaviwfd6d3512019-03-25 13:23:49 -07005808class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005809 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07005810 InputDispatcherTest::SetUp();
5811
Chris Yea209fde2020-07-22 13:54:51 -07005812 std::shared_ptr<FakeApplicationHandle> application =
5813 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005814 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005815 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07005816 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07005817
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005818 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005819 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005820 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07005821
5822 // Set focused application.
5823 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005824 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07005825
5826 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005827 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005828 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005829 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07005830 }
5831
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005832 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07005833 InputDispatcherTest::TearDown();
5834
5835 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005836 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07005837 }
5838
5839protected:
5840 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005841 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07005842 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07005843};
5844
5845// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
5846// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
5847// the onPointerDownOutsideFocus callback.
5848TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07005850 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5851 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005852 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07005853 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07005854
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005855 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07005856 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
5857}
5858
5859// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
5860// DOWN on the window that doesn't have focus. Ensure no window received the
5861// onPointerDownOutsideFocus callback.
5862TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07005864 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005865 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07005866 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07005867
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005868 ASSERT_TRUE(mDispatcher->waitForIdle());
5869 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07005870}
5871
5872// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
5873// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
5874TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5876 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005877 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07005878 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07005879
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005880 ASSERT_TRUE(mDispatcher->waitForIdle());
5881 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07005882}
5883
5884// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
5885// DOWN on the window that already has focus. Ensure no window received the
5886// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005887TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005889 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07005890 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005891 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07005892 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07005893
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005894 ASSERT_TRUE(mDispatcher->waitForIdle());
5895 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07005896}
5897
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08005898// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
5899// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
5900TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
5901 const MotionEvent event =
5902 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5903 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00005904 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08005905 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
5906 .build();
5907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
5908 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5909 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
5910
5911 ASSERT_TRUE(mDispatcher->waitForIdle());
5912 mFakePolicy->assertOnPointerDownWasNotCalled();
5913 // Ensure that the unfocused window did not receive any FOCUS events.
5914 mUnfocusedWindow->assertNoEvents();
5915}
5916
chaviwaf87b3e2019-10-01 16:59:28 -07005917// These tests ensures we can send touch events to a single client when there are multiple input
5918// windows that point to the same client token.
5919class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
5920 virtual void SetUp() override {
5921 InputDispatcherTest::SetUp();
5922
Chris Yea209fde2020-07-22 13:54:51 -07005923 std::shared_ptr<FakeApplicationHandle> application =
5924 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005925 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
5926 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07005927 mWindow1->setFrame(Rect(0, 0, 100, 100));
5928
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005929 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
5930 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07005931 mWindow2->setFrame(Rect(100, 100, 200, 200));
5932
Arthur Hung72d8dc32020-03-28 00:48:39 +00005933 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07005934 }
5935
5936protected:
5937 sp<FakeWindowHandle> mWindow1;
5938 sp<FakeWindowHandle> mWindow2;
5939
5940 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05005941 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07005942 vec2 vals = windowInfo->transform.transform(point.x, point.y);
5943 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07005944 }
5945
5946 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
5947 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005948 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07005949 InputEvent* event = window->consume();
5950
5951 ASSERT_NE(nullptr, event) << name.c_str()
5952 << ": consumer should have returned non-NULL event.";
5953
5954 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
5955 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
5956 << " event, got " << inputEventTypeToString(event->getType()) << " event";
5957
5958 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005959 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08005960 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07005961
5962 for (size_t i = 0; i < points.size(); i++) {
5963 float expectedX = points[i].x;
5964 float expectedY = points[i].y;
5965
5966 EXPECT_EQ(expectedX, motionEvent.getX(i))
5967 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
5968 << ", got " << motionEvent.getX(i);
5969 EXPECT_EQ(expectedY, motionEvent.getY(i))
5970 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
5971 << ", got " << motionEvent.getY(i);
5972 }
5973 }
chaviw9eaa22c2020-07-01 16:21:27 -07005974
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005975 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07005976 std::vector<PointF> expectedPoints) {
5977 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
5978 ADISPLAY_ID_DEFAULT, touchedPoints);
5979 mDispatcher->notifyMotion(&motionArgs);
5980
5981 // Always consume from window1 since it's the window that has the InputReceiver
5982 consumeMotionEvent(mWindow1, action, expectedPoints);
5983 }
chaviwaf87b3e2019-10-01 16:59:28 -07005984};
5985
5986TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
5987 // Touch Window 1
5988 PointF touchedPoint = {10, 10};
5989 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07005990 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07005991
5992 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07005993 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07005994
5995 // Touch Window 2
5996 touchedPoint = {150, 150};
5997 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07005998 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07005999}
6000
chaviw9eaa22c2020-07-01 16:21:27 -07006001TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6002 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006003 mWindow2->setWindowScale(0.5f, 0.5f);
6004
6005 // Touch Window 1
6006 PointF touchedPoint = {10, 10};
6007 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006008 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006009 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006010 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006011
6012 // Touch Window 2
6013 touchedPoint = {150, 150};
6014 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006015 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6016 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006017
chaviw9eaa22c2020-07-01 16:21:27 -07006018 // Update the transform so rotation is set
6019 mWindow2->setWindowTransform(0, -1, 1, 0);
6020 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6021 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006022}
6023
chaviw9eaa22c2020-07-01 16:21:27 -07006024TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006025 mWindow2->setWindowScale(0.5f, 0.5f);
6026
6027 // Touch Window 1
6028 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6029 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006030 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006031
6032 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006033 touchedPoints.push_back(PointF{150, 150});
6034 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006035 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006036
chaviw9eaa22c2020-07-01 16:21:27 -07006037 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006038 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006039 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006040
chaviw9eaa22c2020-07-01 16:21:27 -07006041 // Update the transform so rotation is set for Window 2
6042 mWindow2->setWindowTransform(0, -1, 1, 0);
6043 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006044 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006045}
6046
chaviw9eaa22c2020-07-01 16:21:27 -07006047TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006048 mWindow2->setWindowScale(0.5f, 0.5f);
6049
6050 // Touch Window 1
6051 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6052 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006053 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006054
6055 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006056 touchedPoints.push_back(PointF{150, 150});
6057 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006058
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006059 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006060
6061 // Move both windows
6062 touchedPoints = {{20, 20}, {175, 175}};
6063 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6064 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6065
chaviw9eaa22c2020-07-01 16:21:27 -07006066 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006067
chaviw9eaa22c2020-07-01 16:21:27 -07006068 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006069 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006070 expectedPoints.pop_back();
6071
6072 // Touch Window 2
6073 mWindow2->setWindowTransform(0, -1, 1, 0);
6074 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006075 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006076
6077 // Move both windows
6078 touchedPoints = {{20, 20}, {175, 175}};
6079 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6080 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6081
6082 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006083}
6084
6085TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6086 mWindow1->setWindowScale(0.5f, 0.5f);
6087
6088 // Touch Window 1
6089 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6090 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006091 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006092
6093 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006094 touchedPoints.push_back(PointF{150, 150});
6095 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006096
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006097 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006098
6099 // Move both windows
6100 touchedPoints = {{20, 20}, {175, 175}};
6101 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6102 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6103
chaviw9eaa22c2020-07-01 16:21:27 -07006104 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006105}
6106
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006107class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6108 virtual void SetUp() override {
6109 InputDispatcherTest::SetUp();
6110
Chris Yea209fde2020-07-22 13:54:51 -07006111 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006112 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006113 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6114 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006115 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006116 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006117 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006118
6119 // Set focused application.
6120 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6121
6122 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006123 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006124 mWindow->consumeFocusEvent(true);
6125 }
6126
6127 virtual void TearDown() override {
6128 InputDispatcherTest::TearDown();
6129 mWindow.clear();
6130 }
6131
6132protected:
Chris Yea209fde2020-07-22 13:54:51 -07006133 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006134 sp<FakeWindowHandle> mWindow;
6135 static constexpr PointF WINDOW_LOCATION = {20, 20};
6136
6137 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006138 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006139 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6140 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006141 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006142 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6143 WINDOW_LOCATION));
6144 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006145
6146 sp<FakeWindowHandle> addSpyWindow() {
6147 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006148 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006149 spy->setTrustedOverlay(true);
6150 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006151 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006152 spy->setDispatchingTimeout(30ms);
6153 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6154 return spy;
6155 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006156};
6157
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006158// Send a tap and respond, which should not cause an ANR.
6159TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6160 tapOnWindow();
6161 mWindow->consumeMotionDown();
6162 mWindow->consumeMotionUp();
6163 ASSERT_TRUE(mDispatcher->waitForIdle());
6164 mFakePolicy->assertNotifyAnrWasNotCalled();
6165}
6166
6167// Send a regular key and respond, which should not cause an ANR.
6168TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006169 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006170 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6171 ASSERT_TRUE(mDispatcher->waitForIdle());
6172 mFakePolicy->assertNotifyAnrWasNotCalled();
6173}
6174
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006175TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6176 mWindow->setFocusable(false);
6177 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6178 mWindow->consumeFocusEvent(false);
6179
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006180 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006181 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6182 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6183 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006184 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006185 // Key will not go to window because we have no focused window.
6186 // The 'no focused window' ANR timer should start instead.
6187
6188 // Now, the focused application goes away.
6189 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6190 // The key should get dropped and there should be no ANR.
6191
6192 ASSERT_TRUE(mDispatcher->waitForIdle());
6193 mFakePolicy->assertNotifyAnrWasNotCalled();
6194}
6195
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006196// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006197// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6198// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006199TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006200 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006201 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6202 WINDOW_LOCATION));
6203
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006204 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6205 ASSERT_TRUE(sequenceNum);
6206 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006207 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006208
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006209 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006210 mWindow->consumeMotionEvent(
6211 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006212 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006213 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006214}
6215
6216// Send a key to the app and have the app not respond right away.
6217TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6218 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006220 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6221 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006222 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006223 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006224 ASSERT_TRUE(mDispatcher->waitForIdle());
6225}
6226
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006227// We have a focused application, but no focused window
6228TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006229 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006230 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6231 mWindow->consumeFocusEvent(false);
6232
6233 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006235 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6236 WINDOW_LOCATION));
6237 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6238 mDispatcher->waitForIdle();
6239 mFakePolicy->assertNotifyAnrWasNotCalled();
6240
6241 // Once a focused event arrives, we get an ANR for this application
6242 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6243 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006244 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006245 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6246 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006247 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006248 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006249 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006250 ASSERT_TRUE(mDispatcher->waitForIdle());
6251}
6252
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006253/**
6254 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6255 * there will not be an ANR.
6256 */
6257TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6258 mWindow->setFocusable(false);
6259 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6260 mWindow->consumeFocusEvent(false);
6261
6262 KeyEvent event;
6263 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6264 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6265
6266 // Define a valid key down event that is stale (too old).
6267 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6268 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006269 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006270
6271 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6272
6273 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006274 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006275 InputEventInjectionSync::WAIT_FOR_RESULT,
6276 INJECT_EVENT_TIMEOUT, policyFlags);
6277 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6278 << "Injection should fail because the event is stale";
6279
6280 ASSERT_TRUE(mDispatcher->waitForIdle());
6281 mFakePolicy->assertNotifyAnrWasNotCalled();
6282 mWindow->assertNoEvents();
6283}
6284
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006285// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006286// Make sure that we don't notify policy twice about the same ANR.
6287TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006288 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006289 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6290 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006291
6292 // Once a focused event arrives, we get an ANR for this application
6293 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6294 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006295 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006296 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6297 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006298 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006299 const std::chrono::duration appTimeout =
6300 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6301 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006302
Vishnu Naire4df8752022-09-08 09:17:55 -07006303 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006304 // ANR should not be raised again. It is up to policy to do that if it desires.
6305 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006306
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006307 // If we now get a focused window, the ANR should stop, but the policy handles that via
6308 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006309 ASSERT_TRUE(mDispatcher->waitForIdle());
6310}
6311
6312// We have a focused application, but no focused window
6313TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006314 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006315 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6316 mWindow->consumeFocusEvent(false);
6317
6318 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006319 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006320 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006321 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6322 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006323
Vishnu Naire4df8752022-09-08 09:17:55 -07006324 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6325 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006326
6327 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006328 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006329 ASSERT_TRUE(mDispatcher->waitForIdle());
6330 mWindow->assertNoEvents();
6331}
6332
6333/**
6334 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6335 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6336 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6337 * the ANR mechanism should still work.
6338 *
6339 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6340 * DOWN event, while not responding on the second one.
6341 */
6342TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6343 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6344 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6345 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6346 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6347 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006348 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006349
6350 // Now send ACTION_UP, with identical timestamp
6351 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6352 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6353 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6354 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006355 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006356
6357 // We have now sent down and up. Let's consume first event and then ANR on the second.
6358 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6359 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006360 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006361}
6362
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006363// A spy window can receive an ANR
6364TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6365 sp<FakeWindowHandle> spy = addSpyWindow();
6366
6367 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6368 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6369 WINDOW_LOCATION));
6370 mWindow->consumeMotionDown();
6371
6372 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6373 ASSERT_TRUE(sequenceNum);
6374 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006375 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006376
6377 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006378 spy->consumeMotionEvent(
6379 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006380 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006381 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006382}
6383
6384// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006385// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006386TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6387 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006388
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006389 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6390 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006391 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006393
6394 // Stuck on the ACTION_UP
6395 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006396 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006397
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006398 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006399 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006400 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6401 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006402
6403 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6404 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006405 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006406 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006407 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006408}
6409
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006410// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006411// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006412TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6413 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006414
6415 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006416 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6417 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006418
6419 mWindow->consumeMotionDown();
6420 // Stuck on the ACTION_UP
6421 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006422 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006423
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006424 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006425 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006426 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6427 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006428
6429 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6430 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006431 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006432 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006433 spy->assertNoEvents();
6434}
6435
6436TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6437 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6438
6439 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6440
6441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6442 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6443 WINDOW_LOCATION));
6444
6445 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6446 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6447 ASSERT_TRUE(consumeSeq);
6448
Prabir Pradhanedd96402022-02-15 01:46:16 -08006449 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006450
6451 monitor.finishEvent(*consumeSeq);
6452 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6453
6454 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006455 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006456}
6457
6458// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6459// process events, you don't get an anr. When the window later becomes unresponsive again, you
6460// get an ANR again.
6461// 1. tap -> block on ACTION_UP -> receive ANR
6462// 2. consume all pending events (= queue becomes healthy again)
6463// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6464TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6465 tapOnWindow();
6466
6467 mWindow->consumeMotionDown();
6468 // Block on ACTION_UP
6469 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006470 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006471 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6472 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006473 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006474 mWindow->assertNoEvents();
6475
6476 tapOnWindow();
6477 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006478 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006479 mWindow->consumeMotionUp();
6480
6481 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006482 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006483 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006484 mWindow->assertNoEvents();
6485}
6486
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006487// If a connection remains unresponsive for a while, make sure policy is only notified once about
6488// it.
6489TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006490 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006491 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6492 WINDOW_LOCATION));
6493
6494 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006495 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006496 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006497 // 'notifyConnectionUnresponsive' should only be called once per connection
6498 mFakePolicy->assertNotifyAnrWasNotCalled();
6499 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006500 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006501 mWindow->consumeMotionEvent(
6502 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006503 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006504 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006505 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006506 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006507}
6508
6509/**
6510 * If a window is processing a motion event, and then a key event comes in, the key event should
6511 * not to to the focused window until the motion is processed.
6512 *
6513 * Warning!!!
6514 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
6515 * and the injection timeout that we specify when injecting the key.
6516 * We must have the injection timeout (10ms) be smaller than
6517 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
6518 *
6519 * If that value changes, this test should also change.
6520 */
6521TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
6522 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6523 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6524
6525 tapOnWindow();
6526 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6527 ASSERT_TRUE(downSequenceNum);
6528 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6529 ASSERT_TRUE(upSequenceNum);
6530 // Don't finish the events yet, and send a key
6531 // Injection will "succeed" because we will eventually give up and send the key to the focused
6532 // window even if motions are still being processed. But because the injection timeout is short,
6533 // we will receive INJECTION_TIMED_OUT as the result.
6534
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006535 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006536 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006537 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6538 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006539 // Key will not be sent to the window, yet, because the window is still processing events
6540 // and the key remains pending, waiting for the touch events to be processed
6541 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6542 ASSERT_FALSE(keySequenceNum);
6543
6544 std::this_thread::sleep_for(500ms);
6545 // if we wait long enough though, dispatcher will give up, and still send the key
6546 // to the focused window, even though we have not yet finished the motion event
6547 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6548 mWindow->finishEvent(*downSequenceNum);
6549 mWindow->finishEvent(*upSequenceNum);
6550}
6551
6552/**
6553 * If a window is processing a motion event, and then a key event comes in, the key event should
6554 * not go to the focused window until the motion is processed.
6555 * If then a new motion comes in, then the pending key event should be going to the currently
6556 * focused window right away.
6557 */
6558TEST_F(InputDispatcherSingleWindowAnr,
6559 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
6560 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6561 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6562
6563 tapOnWindow();
6564 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6565 ASSERT_TRUE(downSequenceNum);
6566 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6567 ASSERT_TRUE(upSequenceNum);
6568 // Don't finish the events yet, and send a key
6569 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006570 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006571 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6572 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006573 // At this point, key is still pending, and should not be sent to the application yet.
6574 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6575 ASSERT_FALSE(keySequenceNum);
6576
6577 // Now tap down again. It should cause the pending key to go to the focused window right away.
6578 tapOnWindow();
6579 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
6580 // the other events yet. We can finish events in any order.
6581 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
6582 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
6583 mWindow->consumeMotionDown();
6584 mWindow->consumeMotionUp();
6585 mWindow->assertNoEvents();
6586}
6587
6588class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
6589 virtual void SetUp() override {
6590 InputDispatcherTest::SetUp();
6591
Chris Yea209fde2020-07-22 13:54:51 -07006592 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006593 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006594 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
6595 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006596 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006597 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006598 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006599
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006600 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
6601 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006602 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006603 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006604
6605 // Set focused application.
6606 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07006607 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006608
6609 // Expect one focus window exist in display.
6610 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006611 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006612 mFocusedWindow->consumeFocusEvent(true);
6613 }
6614
6615 virtual void TearDown() override {
6616 InputDispatcherTest::TearDown();
6617
6618 mUnfocusedWindow.clear();
6619 mFocusedWindow.clear();
6620 }
6621
6622protected:
Chris Yea209fde2020-07-22 13:54:51 -07006623 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006624 sp<FakeWindowHandle> mUnfocusedWindow;
6625 sp<FakeWindowHandle> mFocusedWindow;
6626 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
6627 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
6628 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
6629
6630 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
6631
6632 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
6633
6634private:
6635 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006636 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006637 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6638 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006640 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6641 location));
6642 }
6643};
6644
6645// If we have 2 windows that are both unresponsive, the one with the shortest timeout
6646// should be ANR'd first.
6647TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006648 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006649 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6650 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006651 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006652 mFocusedWindow->consumeMotionDown();
6653 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006654 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006655 // We consumed all events, so no ANR
6656 ASSERT_TRUE(mDispatcher->waitForIdle());
6657 mFakePolicy->assertNotifyAnrWasNotCalled();
6658
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006660 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6661 FOCUSED_WINDOW_LOCATION));
6662 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
6663 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006664
6665 const std::chrono::duration timeout =
6666 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006667 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006668 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
6669 // sequence to make it consistent
6670 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006671 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006672 mFocusedWindow->consumeMotionDown();
6673 // This cancel is generated because the connection was unresponsive
6674 mFocusedWindow->consumeMotionCancel();
6675 mFocusedWindow->assertNoEvents();
6676 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006677 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006678 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
6679 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006680 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006681}
6682
6683// If we have 2 windows with identical timeouts that are both unresponsive,
6684// it doesn't matter which order they should have ANR.
6685// But we should receive ANR for both.
6686TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
6687 // Set the timeout for unfocused window to match the focused window
6688 mUnfocusedWindow->setDispatchingTimeout(10ms);
6689 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
6690
6691 tapOnFocusedWindow();
6692 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08006693 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
6694 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
6695 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006696
6697 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006698 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
6699 mFocusedWindow->getToken() == anrConnectionToken2);
6700 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
6701 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006702
6703 ASSERT_TRUE(mDispatcher->waitForIdle());
6704 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006705
6706 mFocusedWindow->consumeMotionDown();
6707 mFocusedWindow->consumeMotionUp();
6708 mUnfocusedWindow->consumeMotionOutside();
6709
Prabir Pradhanedd96402022-02-15 01:46:16 -08006710 sp<IBinder> responsiveToken1, responsiveToken2;
6711 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
6712 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006713
6714 // Both applications should be marked as responsive, in any order
6715 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
6716 mFocusedWindow->getToken() == responsiveToken2);
6717 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
6718 mUnfocusedWindow->getToken() == responsiveToken2);
6719 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006720}
6721
6722// If a window is already not responding, the second tap on the same window should be ignored.
6723// We should also log an error to account for the dropped event (not tested here).
6724// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
6725TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
6726 tapOnFocusedWindow();
6727 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006728 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006729 // Receive the events, but don't respond
6730 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
6731 ASSERT_TRUE(downEventSequenceNum);
6732 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
6733 ASSERT_TRUE(upEventSequenceNum);
6734 const std::chrono::duration timeout =
6735 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006736 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006737
6738 // Tap once again
6739 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006740 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006741 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6742 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006743 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006744 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6745 FOCUSED_WINDOW_LOCATION));
6746 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
6747 // valid touch target
6748 mUnfocusedWindow->assertNoEvents();
6749
6750 // Consume the first tap
6751 mFocusedWindow->finishEvent(*downEventSequenceNum);
6752 mFocusedWindow->finishEvent(*upEventSequenceNum);
6753 ASSERT_TRUE(mDispatcher->waitForIdle());
6754 // The second tap did not go to the focused window
6755 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006756 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08006757 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
6758 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006759 mFakePolicy->assertNotifyAnrWasNotCalled();
6760}
6761
6762// If you tap outside of all windows, there will not be ANR
6763TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006764 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006765 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6766 LOCATION_OUTSIDE_ALL_WINDOWS));
6767 ASSERT_TRUE(mDispatcher->waitForIdle());
6768 mFakePolicy->assertNotifyAnrWasNotCalled();
6769}
6770
6771// Since the focused window is paused, tapping on it should not produce any events
6772TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
6773 mFocusedWindow->setPaused(true);
6774 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
6775
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006776 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006777 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6778 FOCUSED_WINDOW_LOCATION));
6779
6780 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
6781 ASSERT_TRUE(mDispatcher->waitForIdle());
6782 // Should not ANR because the window is paused, and touches shouldn't go to it
6783 mFakePolicy->assertNotifyAnrWasNotCalled();
6784
6785 mFocusedWindow->assertNoEvents();
6786 mUnfocusedWindow->assertNoEvents();
6787}
6788
6789/**
6790 * If a window is processing a motion event, and then a key event comes in, the key event should
6791 * not to to the focused window until the motion is processed.
6792 * If a different window becomes focused at this time, the key should go to that window instead.
6793 *
6794 * Warning!!!
6795 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
6796 * and the injection timeout that we specify when injecting the key.
6797 * We must have the injection timeout (10ms) be smaller than
6798 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
6799 *
6800 * If that value changes, this test should also change.
6801 */
6802TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
6803 // Set a long ANR timeout to prevent it from triggering
6804 mFocusedWindow->setDispatchingTimeout(2s);
6805 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
6806
6807 tapOnUnfocusedWindow();
6808 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
6809 ASSERT_TRUE(downSequenceNum);
6810 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
6811 ASSERT_TRUE(upSequenceNum);
6812 // Don't finish the events yet, and send a key
6813 // Injection will succeed because we will eventually give up and send the key to the focused
6814 // window even if motions are still being processed.
6815
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006816 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006817 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6818 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006820 // Key will not be sent to the window, yet, because the window is still processing events
6821 // and the key remains pending, waiting for the touch events to be processed
6822 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
6823 ASSERT_FALSE(keySequenceNum);
6824
6825 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07006826 mFocusedWindow->setFocusable(false);
6827 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006828 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006829 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006830
6831 // Focus events should precede the key events
6832 mUnfocusedWindow->consumeFocusEvent(true);
6833 mFocusedWindow->consumeFocusEvent(false);
6834
6835 // Finish the tap events, which should unblock dispatcher
6836 mUnfocusedWindow->finishEvent(*downSequenceNum);
6837 mUnfocusedWindow->finishEvent(*upSequenceNum);
6838
6839 // Now that all queues are cleared and no backlog in the connections, the key event
6840 // can finally go to the newly focused "mUnfocusedWindow".
6841 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6842 mFocusedWindow->assertNoEvents();
6843 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006844 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006845}
6846
6847// When the touch stream is split across 2 windows, and one of them does not respond,
6848// then ANR should be raised and the touch should be canceled for the unresponsive window.
6849// The other window should not be affected by that.
6850TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
6851 // Touch Window 1
6852 NotifyMotionArgs motionArgs =
6853 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6854 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
6855 mDispatcher->notifyMotion(&motionArgs);
6856 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006857 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006858
6859 // Touch Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006860 motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6861 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006862 mDispatcher->notifyMotion(&motionArgs);
6863
6864 const std::chrono::duration timeout =
6865 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006866 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006867
6868 mUnfocusedWindow->consumeMotionDown();
6869 mFocusedWindow->consumeMotionDown();
6870 // Focused window may or may not receive ACTION_MOVE
6871 // But it should definitely receive ACTION_CANCEL due to the ANR
6872 InputEvent* event;
6873 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
6874 ASSERT_TRUE(moveOrCancelSequenceNum);
6875 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
6876 ASSERT_NE(nullptr, event);
6877 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
6878 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
6879 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
6880 mFocusedWindow->consumeMotionCancel();
6881 } else {
6882 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
6883 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006884 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006885 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
6886 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006887
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006888 mUnfocusedWindow->assertNoEvents();
6889 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006890 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006891}
6892
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05006893/**
6894 * If we have no focused window, and a key comes in, we start the ANR timer.
6895 * The focused application should add a focused window before the timer runs out to prevent ANR.
6896 *
6897 * If the user touches another application during this time, the key should be dropped.
6898 * Next, if a new focused window comes in, without toggling the focused application,
6899 * then no ANR should occur.
6900 *
6901 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
6902 * but in some cases the policy may not update the focused application.
6903 */
6904TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
6905 std::shared_ptr<FakeApplicationHandle> focusedApplication =
6906 std::make_shared<FakeApplicationHandle>();
6907 focusedApplication->setDispatchingTimeout(60ms);
6908 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
6909 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
6910 mFocusedWindow->setFocusable(false);
6911
6912 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
6913 mFocusedWindow->consumeFocusEvent(false);
6914
6915 // Send a key. The ANR timer should start because there is no focused window.
6916 // 'focusedApplication' will get blamed if this timer completes.
6917 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006918 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006919 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6920 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6921 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05006923
6924 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
6925 // then the injected touches won't cause the focused event to get dropped.
6926 // The dispatcher only checks for whether the queue should be pruned upon queueing.
6927 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
6928 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
6929 // For this test, it means that the key would get delivered to the window once it becomes
6930 // focused.
6931 std::this_thread::sleep_for(10ms);
6932
6933 // Touch unfocused window. This should force the pending key to get dropped.
6934 NotifyMotionArgs motionArgs =
6935 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6936 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
6937 mDispatcher->notifyMotion(&motionArgs);
6938
6939 // We do not consume the motion right away, because that would require dispatcher to first
6940 // process (== drop) the key event, and by that time, ANR will be raised.
6941 // Set the focused window first.
6942 mFocusedWindow->setFocusable(true);
6943 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
6944 setFocusedWindow(mFocusedWindow);
6945 mFocusedWindow->consumeFocusEvent(true);
6946 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
6947 // to another application. This could be a bug / behaviour in the policy.
6948
6949 mUnfocusedWindow->consumeMotionDown();
6950
6951 ASSERT_TRUE(mDispatcher->waitForIdle());
6952 // Should not ANR because we actually have a focused window. It was just added too slowly.
6953 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
6954}
6955
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05006956// These tests ensure we cannot send touch events to a window that's positioned behind a window
6957// that has feature NO_INPUT_CHANNEL.
6958// Layout:
6959// Top (closest to user)
6960// mNoInputWindow (above all windows)
6961// mBottomWindow
6962// Bottom (furthest from user)
6963class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
6964 virtual void SetUp() override {
6965 InputDispatcherTest::SetUp();
6966
6967 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006968 mNoInputWindow =
6969 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
6970 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006971 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006972 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05006973 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
6974 // It's perfectly valid for this window to not have an associated input channel
6975
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006976 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
6977 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05006978 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
6979
6980 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
6981 }
6982
6983protected:
6984 std::shared_ptr<FakeApplicationHandle> mApplication;
6985 sp<FakeWindowHandle> mNoInputWindow;
6986 sp<FakeWindowHandle> mBottomWindow;
6987};
6988
6989TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
6990 PointF touchedPoint = {10, 10};
6991
6992 NotifyMotionArgs motionArgs =
6993 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6994 ADISPLAY_ID_DEFAULT, {touchedPoint});
6995 mDispatcher->notifyMotion(&motionArgs);
6996
6997 mNoInputWindow->assertNoEvents();
6998 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
6999 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7000 // and therefore should prevent mBottomWindow from receiving touches
7001 mBottomWindow->assertNoEvents();
7002}
7003
7004/**
7005 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7006 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7007 */
7008TEST_F(InputDispatcherMultiWindowOcclusionTests,
7009 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007010 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7011 "Window with input channel and NO_INPUT_CHANNEL",
7012 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007013
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007014 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007015 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7016 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7017
7018 PointF touchedPoint = {10, 10};
7019
7020 NotifyMotionArgs motionArgs =
7021 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7022 ADISPLAY_ID_DEFAULT, {touchedPoint});
7023 mDispatcher->notifyMotion(&motionArgs);
7024
7025 mNoInputWindow->assertNoEvents();
7026 mBottomWindow->assertNoEvents();
7027}
7028
Vishnu Nair958da932020-08-21 17:12:37 -07007029class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7030protected:
7031 std::shared_ptr<FakeApplicationHandle> mApp;
7032 sp<FakeWindowHandle> mWindow;
7033 sp<FakeWindowHandle> mMirror;
7034
7035 virtual void SetUp() override {
7036 InputDispatcherTest::SetUp();
7037 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007038 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7039 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7040 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007041 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7042 mWindow->setFocusable(true);
7043 mMirror->setFocusable(true);
7044 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7045 }
7046};
7047
7048TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7049 // Request focus on a mirrored window
7050 setFocusedWindow(mMirror);
7051
7052 // window gets focused
7053 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7055 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007056 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7057}
7058
7059// A focused & mirrored window remains focused only if the window and its mirror are both
7060// focusable.
7061TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7062 setFocusedWindow(mMirror);
7063
7064 // window gets focused
7065 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7067 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007068 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7070 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007071 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7072
7073 mMirror->setFocusable(false);
7074 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7075
7076 // window loses focus since one of the windows associated with the token in not focusable
7077 mWindow->consumeFocusEvent(false);
7078
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007079 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7080 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007081 mWindow->assertNoEvents();
7082}
7083
7084// A focused & mirrored window remains focused until the window and its mirror both become
7085// invisible.
7086TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7087 setFocusedWindow(mMirror);
7088
7089 // window gets focused
7090 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007091 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7092 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007093 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007094 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7095 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007096 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7097
7098 mMirror->setVisible(false);
7099 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7100
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007101 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7102 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007103 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007104 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7105 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007106 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7107
7108 mWindow->setVisible(false);
7109 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7110
7111 // window loses focus only after all windows associated with the token become invisible.
7112 mWindow->consumeFocusEvent(false);
7113
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007114 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7115 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007116 mWindow->assertNoEvents();
7117}
7118
7119// A focused & mirrored window remains focused until both windows are removed.
7120TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7121 setFocusedWindow(mMirror);
7122
7123 // window gets focused
7124 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007125 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7126 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007127 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007128 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7129 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007130 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7131
7132 // single window is removed but the window token remains focused
7133 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7134
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007135 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7136 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007137 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007138 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7139 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007140 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7141
7142 // Both windows are removed
7143 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7144 mWindow->consumeFocusEvent(false);
7145
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007146 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7147 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007148 mWindow->assertNoEvents();
7149}
7150
7151// Focus request can be pending until one window becomes visible.
7152TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7153 // Request focus on an invisible mirror.
7154 mWindow->setVisible(false);
7155 mMirror->setVisible(false);
7156 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7157 setFocusedWindow(mMirror);
7158
7159 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007160 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007161 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7162 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007163
7164 mMirror->setVisible(true);
7165 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7166
7167 // window gets focused
7168 mWindow->consumeFocusEvent(true);
7169 // window gets the pending key event
7170 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7171}
Prabir Pradhan99987712020-11-10 18:43:05 -08007172
7173class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7174protected:
7175 std::shared_ptr<FakeApplicationHandle> mApp;
7176 sp<FakeWindowHandle> mWindow;
7177 sp<FakeWindowHandle> mSecondWindow;
7178
7179 void SetUp() override {
7180 InputDispatcherTest::SetUp();
7181 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007182 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007183 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007184 mSecondWindow =
7185 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007186 mSecondWindow->setFocusable(true);
7187
7188 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7189 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7190
7191 setFocusedWindow(mWindow);
7192 mWindow->consumeFocusEvent(true);
7193 }
7194
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007195 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
7196 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007197 mDispatcher->notifyPointerCaptureChanged(&args);
7198 }
7199
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007200 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7201 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007202 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007203 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7204 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007205 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007206 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007207 }
7208};
7209
7210TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7211 // Ensure that capture cannot be obtained for unfocused windows.
7212 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7213 mFakePolicy->assertSetPointerCaptureNotCalled();
7214 mSecondWindow->assertNoEvents();
7215
7216 // Ensure that capture can be enabled from the focus window.
7217 requestAndVerifyPointerCapture(mWindow, true);
7218
7219 // Ensure that capture cannot be disabled from a window that does not have capture.
7220 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7221 mFakePolicy->assertSetPointerCaptureNotCalled();
7222
7223 // Ensure that capture can be disabled from the window with capture.
7224 requestAndVerifyPointerCapture(mWindow, false);
7225}
7226
7227TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007228 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007229
7230 setFocusedWindow(mSecondWindow);
7231
7232 // Ensure that the capture disabled event was sent first.
7233 mWindow->consumeCaptureEvent(false);
7234 mWindow->consumeFocusEvent(false);
7235 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007236 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007237
7238 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007239 notifyPointerCaptureChanged({});
7240 notifyPointerCaptureChanged(request);
7241 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007242 mWindow->assertNoEvents();
7243 mSecondWindow->assertNoEvents();
7244 mFakePolicy->assertSetPointerCaptureNotCalled();
7245}
7246
7247TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007248 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007249
7250 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007251 notifyPointerCaptureChanged({});
7252 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007253
7254 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007255 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007256 mWindow->consumeCaptureEvent(false);
7257 mWindow->assertNoEvents();
7258}
7259
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007260TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7261 requestAndVerifyPointerCapture(mWindow, true);
7262
7263 // The first window loses focus.
7264 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007265 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007266 mWindow->consumeCaptureEvent(false);
7267
7268 // Request Pointer Capture from the second window before the notification from InputReader
7269 // arrives.
7270 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007271 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007272
7273 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007274 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007275
7276 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007277 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007278
7279 mSecondWindow->consumeFocusEvent(true);
7280 mSecondWindow->consumeCaptureEvent(true);
7281}
7282
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007283TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7284 // App repeatedly enables and disables capture.
7285 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7286 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7287 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7288 mFakePolicy->assertSetPointerCaptureCalled(false);
7289 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7290 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7291
7292 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7293 // first request is now stale, this should do nothing.
7294 notifyPointerCaptureChanged(firstRequest);
7295 mWindow->assertNoEvents();
7296
7297 // InputReader notifies that the second request was enabled.
7298 notifyPointerCaptureChanged(secondRequest);
7299 mWindow->consumeCaptureEvent(true);
7300}
7301
Prabir Pradhan7092e262022-05-03 16:51:09 +00007302TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7303 requestAndVerifyPointerCapture(mWindow, true);
7304
7305 // App toggles pointer capture off and on.
7306 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7307 mFakePolicy->assertSetPointerCaptureCalled(false);
7308
7309 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7310 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7311
7312 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7313 // preceding "disable" request.
7314 notifyPointerCaptureChanged(enableRequest);
7315
7316 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7317 // any notifications.
7318 mWindow->assertNoEvents();
7319}
7320
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007321class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7322protected:
7323 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007324
7325 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7326 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7327
7328 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7329 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7330
7331 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7332 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7333 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7334 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7335 MAXIMUM_OBSCURING_OPACITY);
7336
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007337 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007338 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007339 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007340
7341 sp<FakeWindowHandle> mTouchWindow;
7342
7343 virtual void SetUp() override {
7344 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007345 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007346 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7347 }
7348
7349 virtual void TearDown() override {
7350 InputDispatcherTest::TearDown();
7351 mTouchWindow.clear();
7352 }
7353
chaviw3277faf2021-05-19 16:45:23 -05007354 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
7355 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007356 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007357 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007358 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007359 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007360 return window;
7361 }
7362
7363 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
7364 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7365 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007366 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007367 // Generate an arbitrary PID based on the UID
7368 window->setOwnerInfo(1777 + (uid % 10000), uid);
7369 return window;
7370 }
7371
7372 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
7373 NotifyMotionArgs args =
7374 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7375 ADISPLAY_ID_DEFAULT, points);
7376 mDispatcher->notifyMotion(&args);
7377 }
7378};
7379
7380TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007381 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007382 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007383 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007384
7385 touch();
7386
7387 mTouchWindow->assertNoEvents();
7388}
7389
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007390TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007391 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7392 const sp<FakeWindowHandle>& w =
7393 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7394 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7395
7396 touch();
7397
7398 mTouchWindow->assertNoEvents();
7399}
7400
7401TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007402 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7403 const sp<FakeWindowHandle>& w =
7404 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7405 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7406
7407 touch();
7408
7409 w->assertNoEvents();
7410}
7411
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007412TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007413 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7414 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007415
7416 touch();
7417
7418 mTouchWindow->consumeAnyMotionDown();
7419}
7420
7421TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007422 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007423 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007424 w->setFrame(Rect(0, 0, 50, 50));
7425 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007426
7427 touch({PointF{100, 100}});
7428
7429 mTouchWindow->consumeAnyMotionDown();
7430}
7431
7432TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007433 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007434 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007435 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7436
7437 touch();
7438
7439 mTouchWindow->consumeAnyMotionDown();
7440}
7441
7442TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7443 const sp<FakeWindowHandle>& w =
7444 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7445 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007446
7447 touch();
7448
7449 mTouchWindow->consumeAnyMotionDown();
7450}
7451
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007452TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7453 const sp<FakeWindowHandle>& w =
7454 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7455 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7456
7457 touch();
7458
7459 w->assertNoEvents();
7460}
7461
7462/**
7463 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
7464 * inside) while letting them pass-through. Note that even though touch passes through the occluding
7465 * window, the occluding window will still receive ACTION_OUTSIDE event.
7466 */
7467TEST_F(InputDispatcherUntrustedTouchesTest,
7468 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
7469 const sp<FakeWindowHandle>& w =
7470 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007471 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007472 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7473
7474 touch();
7475
7476 w->consumeMotionOutside();
7477}
7478
7479TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
7480 const sp<FakeWindowHandle>& w =
7481 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007482 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007483 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7484
7485 touch();
7486
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007487 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007488}
7489
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007490TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007491 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007492 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7493 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007494 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7495
7496 touch();
7497
7498 mTouchWindow->consumeAnyMotionDown();
7499}
7500
7501TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
7502 const sp<FakeWindowHandle>& w =
7503 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7504 MAXIMUM_OBSCURING_OPACITY);
7505 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007506
7507 touch();
7508
7509 mTouchWindow->consumeAnyMotionDown();
7510}
7511
7512TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007513 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007514 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7515 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007516 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7517
7518 touch();
7519
7520 mTouchWindow->assertNoEvents();
7521}
7522
7523TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
7524 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
7525 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007526 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7527 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007528 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007529 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7530 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007531 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7532
7533 touch();
7534
7535 mTouchWindow->assertNoEvents();
7536}
7537
7538TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
7539 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
7540 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007541 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7542 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007543 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007544 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7545 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007546 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7547
7548 touch();
7549
7550 mTouchWindow->consumeAnyMotionDown();
7551}
7552
7553TEST_F(InputDispatcherUntrustedTouchesTest,
7554 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
7555 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007556 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7557 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007558 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007559 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7560 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007561 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
7562
7563 touch();
7564
7565 mTouchWindow->consumeAnyMotionDown();
7566}
7567
7568TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
7569 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007570 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7571 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007572 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007573 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7574 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007575 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007576
7577 touch();
7578
7579 mTouchWindow->assertNoEvents();
7580}
7581
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007582TEST_F(InputDispatcherUntrustedTouchesTest,
7583 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
7584 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007585 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7586 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007587 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007588 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7589 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007590 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7591
7592 touch();
7593
7594 mTouchWindow->assertNoEvents();
7595}
7596
7597TEST_F(InputDispatcherUntrustedTouchesTest,
7598 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
7599 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007600 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7601 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007602 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007603 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7604 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007605 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7606
7607 touch();
7608
7609 mTouchWindow->consumeAnyMotionDown();
7610}
7611
7612TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
7613 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007614 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7615 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007616 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7617
7618 touch();
7619
7620 mTouchWindow->consumeAnyMotionDown();
7621}
7622
7623TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
7624 const sp<FakeWindowHandle>& w =
7625 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
7626 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7627
7628 touch();
7629
7630 mTouchWindow->consumeAnyMotionDown();
7631}
7632
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00007633TEST_F(InputDispatcherUntrustedTouchesTest,
7634 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
7635 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
7636 const sp<FakeWindowHandle>& w =
7637 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
7638 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7639
7640 touch();
7641
7642 mTouchWindow->assertNoEvents();
7643}
7644
7645TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
7646 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
7647 const sp<FakeWindowHandle>& w =
7648 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
7649 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7650
7651 touch();
7652
7653 mTouchWindow->consumeAnyMotionDown();
7654}
7655
7656TEST_F(InputDispatcherUntrustedTouchesTest,
7657 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
7658 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
7659 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007660 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7661 OPACITY_ABOVE_THRESHOLD);
7662 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7663
7664 touch();
7665
7666 mTouchWindow->consumeAnyMotionDown();
7667}
7668
7669TEST_F(InputDispatcherUntrustedTouchesTest,
7670 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
7671 const sp<FakeWindowHandle>& w1 =
7672 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
7673 OPACITY_BELOW_THRESHOLD);
7674 const sp<FakeWindowHandle>& w2 =
7675 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7676 OPACITY_BELOW_THRESHOLD);
7677 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7678
7679 touch();
7680
7681 mTouchWindow->assertNoEvents();
7682}
7683
7684/**
7685 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
7686 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
7687 * (which alone would result in allowing touches) does not affect the blocking behavior.
7688 */
7689TEST_F(InputDispatcherUntrustedTouchesTest,
7690 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
7691 const sp<FakeWindowHandle>& wB =
7692 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
7693 OPACITY_BELOW_THRESHOLD);
7694 const sp<FakeWindowHandle>& wC =
7695 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7696 OPACITY_BELOW_THRESHOLD);
7697 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
7698
7699 touch();
7700
7701 mTouchWindow->assertNoEvents();
7702}
7703
7704/**
7705 * This test is testing that a window from a different UID but with same application token doesn't
7706 * block the touch. Apps can share the application token for close UI collaboration for example.
7707 */
7708TEST_F(InputDispatcherUntrustedTouchesTest,
7709 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
7710 const sp<FakeWindowHandle>& w =
7711 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7712 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00007713 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7714
7715 touch();
7716
7717 mTouchWindow->consumeAnyMotionDown();
7718}
7719
arthurhungb89ccb02020-12-30 16:19:01 +08007720class InputDispatcherDragTests : public InputDispatcherTest {
7721protected:
7722 std::shared_ptr<FakeApplicationHandle> mApp;
7723 sp<FakeWindowHandle> mWindow;
7724 sp<FakeWindowHandle> mSecondWindow;
7725 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007726 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007727 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
7728 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08007729
7730 void SetUp() override {
7731 InputDispatcherTest::SetUp();
7732 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007733 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08007734 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08007735
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007736 mSecondWindow =
7737 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08007738 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08007739
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007740 mSpyWindow =
7741 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007742 mSpyWindow->setSpy(true);
7743 mSpyWindow->setTrustedOverlay(true);
7744 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
7745
arthurhungb89ccb02020-12-30 16:19:01 +08007746 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007747 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08007748 }
7749
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007750 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
7751 switch (fromSource) {
7752 case AINPUT_SOURCE_TOUCHSCREEN:
7753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7754 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7755 ADISPLAY_ID_DEFAULT, {50, 50}))
7756 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7757 break;
7758 case AINPUT_SOURCE_STYLUS:
7759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7760 injectMotionEvent(
7761 mDispatcher,
7762 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
7763 AINPUT_SOURCE_STYLUS)
7764 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
7765 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
7766 .x(50)
7767 .y(50))
7768 .build()));
7769 break;
7770 case AINPUT_SOURCE_MOUSE:
7771 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7772 injectMotionEvent(
7773 mDispatcher,
7774 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7775 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
7776 .pointer(PointerBuilder(MOUSE_POINTER_ID,
7777 AMOTION_EVENT_TOOL_TYPE_MOUSE)
7778 .x(50)
7779 .y(50))
7780 .build()));
7781 break;
7782 default:
7783 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
7784 }
arthurhungb89ccb02020-12-30 16:19:01 +08007785
7786 // Window should receive motion event.
7787 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007788 // Spy window should also receive motion event
7789 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00007790 }
7791
7792 // Start performing drag, we will create a drag window and transfer touch to it.
7793 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
7794 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007795 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00007796 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007797 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00007798 }
arthurhungb89ccb02020-12-30 16:19:01 +08007799
7800 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007801 mDragWindow =
7802 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007803 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08007804 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007805 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08007806
7807 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00007808 bool transferred =
7809 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00007810 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00007811 if (transferred) {
7812 mWindow->consumeMotionCancel();
7813 mDragWindow->consumeMotionDown();
7814 }
7815 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08007816 }
7817};
7818
7819TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007820 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08007821
7822 // Move on window.
7823 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7824 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7825 ADISPLAY_ID_DEFAULT, {50, 50}))
7826 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7827 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7828 mWindow->consumeDragEvent(false, 50, 50);
7829 mSecondWindow->assertNoEvents();
7830
7831 // Move to another window.
7832 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7833 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7834 ADISPLAY_ID_DEFAULT, {150, 50}))
7835 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7836 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7837 mWindow->consumeDragEvent(true, 150, 50);
7838 mSecondWindow->consumeDragEvent(false, 50, 50);
7839
7840 // Move back to original window.
7841 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7842 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7843 ADISPLAY_ID_DEFAULT, {50, 50}))
7844 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7845 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7846 mWindow->consumeDragEvent(false, 50, 50);
7847 mSecondWindow->consumeDragEvent(true, -50, 50);
7848
7849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7850 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
7851 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7852 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7853 mWindow->assertNoEvents();
7854 mSecondWindow->assertNoEvents();
7855}
7856
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007857TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007858 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007859
7860 // No cancel event after drag start
7861 mSpyWindow->assertNoEvents();
7862
7863 const MotionEvent secondFingerDownEvent =
7864 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7865 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00007866 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7867 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007868 .build();
7869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7870 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7871 InputEventInjectionSync::WAIT_FOR_RESULT))
7872 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7873
7874 // Receives cancel for first pointer after next pointer down
7875 mSpyWindow->consumeMotionCancel();
7876 mSpyWindow->consumeMotionDown();
7877
7878 mSpyWindow->assertNoEvents();
7879}
7880
arthurhungf452d0b2021-01-06 00:19:52 +08007881TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007882 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08007883
7884 // Move on window.
7885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7886 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7887 ADISPLAY_ID_DEFAULT, {50, 50}))
7888 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7889 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7890 mWindow->consumeDragEvent(false, 50, 50);
7891 mSecondWindow->assertNoEvents();
7892
7893 // Move to another window.
7894 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7895 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7896 ADISPLAY_ID_DEFAULT, {150, 50}))
7897 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7898 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7899 mWindow->consumeDragEvent(true, 150, 50);
7900 mSecondWindow->consumeDragEvent(false, 50, 50);
7901
7902 // drop to another window.
7903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7904 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7905 {150, 50}))
7906 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7907 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7908 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
7909 mWindow->assertNoEvents();
7910 mSecondWindow->assertNoEvents();
7911}
7912
arthurhung6d4bed92021-03-17 11:59:33 +08007913TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007914 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08007915
7916 // Move on window and keep button pressed.
7917 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7918 injectMotionEvent(mDispatcher,
7919 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
7920 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
7921 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
7922 .x(50)
7923 .y(50))
7924 .build()))
7925 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7926 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7927 mWindow->consumeDragEvent(false, 50, 50);
7928 mSecondWindow->assertNoEvents();
7929
7930 // Move to another window and release button, expect to drop item.
7931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7932 injectMotionEvent(mDispatcher,
7933 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
7934 .buttonState(0)
7935 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
7936 .x(150)
7937 .y(50))
7938 .build()))
7939 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7940 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7941 mWindow->assertNoEvents();
7942 mSecondWindow->assertNoEvents();
7943 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
7944
7945 // nothing to the window.
7946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7947 injectMotionEvent(mDispatcher,
7948 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
7949 .buttonState(0)
7950 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
7951 .x(150)
7952 .y(50))
7953 .build()))
7954 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7955 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7956 mWindow->assertNoEvents();
7957 mSecondWindow->assertNoEvents();
7958}
7959
Arthur Hung54745652022-04-20 07:17:41 +00007960TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007961 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08007962
7963 // Set second window invisible.
7964 mSecondWindow->setVisible(false);
7965 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
7966
7967 // Move on window.
7968 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7969 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7970 ADISPLAY_ID_DEFAULT, {50, 50}))
7971 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7972 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7973 mWindow->consumeDragEvent(false, 50, 50);
7974 mSecondWindow->assertNoEvents();
7975
7976 // Move to another window.
7977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7978 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7979 ADISPLAY_ID_DEFAULT, {150, 50}))
7980 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7981 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7982 mWindow->consumeDragEvent(true, 150, 50);
7983 mSecondWindow->assertNoEvents();
7984
7985 // drop to another window.
7986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7987 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7988 {150, 50}))
7989 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7990 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7991 mFakePolicy->assertDropTargetEquals(nullptr);
7992 mWindow->assertNoEvents();
7993 mSecondWindow->assertNoEvents();
7994}
7995
Arthur Hung54745652022-04-20 07:17:41 +00007996TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007997 // Ensure window could track pointerIds if it didn't support split touch.
7998 mWindow->setPreventSplitting(true);
7999
Arthur Hung54745652022-04-20 07:17:41 +00008000 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8001 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8002 {50, 50}))
8003 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8004 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8005
8006 const MotionEvent secondFingerDownEvent =
8007 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8008 .displayId(ADISPLAY_ID_DEFAULT)
8009 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008010 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
8011 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008012 .build();
8013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8014 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8015 InputEventInjectionSync::WAIT_FOR_RESULT))
8016 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008017 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008018
8019 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008020 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008021}
8022
8023TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8024 // First down on second window.
8025 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8026 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8027 {150, 50}))
8028 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8029
8030 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8031
8032 // Second down on first window.
8033 const MotionEvent secondFingerDownEvent =
8034 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8035 .displayId(ADISPLAY_ID_DEFAULT)
8036 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008037 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
8038 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008039 .build();
8040 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8041 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8042 InputEventInjectionSync::WAIT_FOR_RESULT))
8043 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8044 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8045
8046 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008047 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008048
8049 // Move on window.
8050 const MotionEvent secondFingerMoveEvent =
8051 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8052 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008053 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
8054 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008055 .build();
8056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8057 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8058 InputEventInjectionSync::WAIT_FOR_RESULT));
8059 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8060 mWindow->consumeDragEvent(false, 50, 50);
8061 mSecondWindow->consumeMotionMove();
8062
8063 // Release the drag pointer should perform drop.
8064 const MotionEvent secondFingerUpEvent =
8065 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8066 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008067 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
8068 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008069 .build();
8070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8071 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8072 InputEventInjectionSync::WAIT_FOR_RESULT));
8073 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8074 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
8075 mWindow->assertNoEvents();
8076 mSecondWindow->consumeMotionMove();
8077}
8078
Arthur Hung3915c1f2022-05-31 07:17:17 +00008079TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008080 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008081
8082 // Update window of second display.
8083 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008084 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008085 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8086
8087 // Let second display has a touch state.
8088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8089 injectMotionEvent(mDispatcher,
8090 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8091 AINPUT_SOURCE_TOUCHSCREEN)
8092 .displayId(SECOND_DISPLAY_ID)
8093 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
8094 .x(100)
8095 .y(100))
8096 .build()));
8097 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008098 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008099 // Update window again.
8100 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8101
8102 // Move on window.
8103 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8104 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8105 ADISPLAY_ID_DEFAULT, {50, 50}))
8106 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8107 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8108 mWindow->consumeDragEvent(false, 50, 50);
8109 mSecondWindow->assertNoEvents();
8110
8111 // Move to another window.
8112 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8113 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8114 ADISPLAY_ID_DEFAULT, {150, 50}))
8115 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8116 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8117 mWindow->consumeDragEvent(true, 150, 50);
8118 mSecondWindow->consumeDragEvent(false, 50, 50);
8119
8120 // drop to another window.
8121 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8122 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8123 {150, 50}))
8124 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8125 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8126 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8127 mWindow->assertNoEvents();
8128 mSecondWindow->assertNoEvents();
8129}
8130
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008131TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8132 startDrag(true, AINPUT_SOURCE_MOUSE);
8133 // Move on window.
8134 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8135 injectMotionEvent(mDispatcher,
8136 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8137 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8138 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8139 AMOTION_EVENT_TOOL_TYPE_MOUSE)
8140 .x(50)
8141 .y(50))
8142 .build()))
8143 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8144 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8145 mWindow->consumeDragEvent(false, 50, 50);
8146 mSecondWindow->assertNoEvents();
8147
8148 // Move to another window.
8149 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8150 injectMotionEvent(mDispatcher,
8151 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8152 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8153 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8154 AMOTION_EVENT_TOOL_TYPE_MOUSE)
8155 .x(150)
8156 .y(50))
8157 .build()))
8158 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8159 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8160 mWindow->consumeDragEvent(true, 150, 50);
8161 mSecondWindow->consumeDragEvent(false, 50, 50);
8162
8163 // drop to another window.
8164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8165 injectMotionEvent(mDispatcher,
8166 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8167 .buttonState(0)
8168 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8169 AMOTION_EVENT_TOOL_TYPE_MOUSE)
8170 .x(150)
8171 .y(50))
8172 .build()))
8173 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8174 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8175 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8176 mWindow->assertNoEvents();
8177 mSecondWindow->assertNoEvents();
8178}
8179
Vishnu Nair062a8672021-09-03 16:07:44 -07008180class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8181
8182TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8183 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008184 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8185 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008186 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008187 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8188 window->setFocusable(true);
8189 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8190 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008191 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008192
8193 // With the flag set, window should not get any input
8194 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
8195 mDispatcher->notifyKey(&keyArgs);
8196 window->assertNoEvents();
8197
8198 NotifyMotionArgs motionArgs =
8199 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8200 ADISPLAY_ID_DEFAULT);
8201 mDispatcher->notifyMotion(&motionArgs);
8202 window->assertNoEvents();
8203
8204 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008205 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008206 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8207
8208 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
8209 mDispatcher->notifyKey(&keyArgs);
8210 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8211
8212 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8213 ADISPLAY_ID_DEFAULT);
8214 mDispatcher->notifyMotion(&motionArgs);
8215 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8216 window->assertNoEvents();
8217}
8218
8219TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8220 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8221 std::make_shared<FakeApplicationHandle>();
8222 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008223 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8224 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008225 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8226 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008227 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008228 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008229 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8230 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008231 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008232 window->setOwnerInfo(222, 222);
8233 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8234 window->setFocusable(true);
8235 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8236 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008237 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008238
8239 // With the flag set, window should not get any input
8240 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
8241 mDispatcher->notifyKey(&keyArgs);
8242 window->assertNoEvents();
8243
8244 NotifyMotionArgs motionArgs =
8245 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8246 ADISPLAY_ID_DEFAULT);
8247 mDispatcher->notifyMotion(&motionArgs);
8248 window->assertNoEvents();
8249
8250 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008251 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008252 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8253
8254 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
8255 mDispatcher->notifyKey(&keyArgs);
8256 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8257
8258 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8259 ADISPLAY_ID_DEFAULT);
8260 mDispatcher->notifyMotion(&motionArgs);
8261 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8262 window->assertNoEvents();
8263}
8264
8265TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8266 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8267 std::make_shared<FakeApplicationHandle>();
8268 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008269 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8270 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008271 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8272 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008273 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008274 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008275 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8276 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008277 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008278 window->setOwnerInfo(222, 222);
8279 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8280 window->setFocusable(true);
8281 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8282 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008283 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008284
8285 // With the flag set, window should not get any input
8286 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
8287 mDispatcher->notifyKey(&keyArgs);
8288 window->assertNoEvents();
8289
8290 NotifyMotionArgs motionArgs =
8291 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8292 ADISPLAY_ID_DEFAULT);
8293 mDispatcher->notifyMotion(&motionArgs);
8294 window->assertNoEvents();
8295
8296 // When the window is no longer obscured because it went on top, it should get input
8297 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8298
8299 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
8300 mDispatcher->notifyKey(&keyArgs);
8301 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8302
8303 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8304 ADISPLAY_ID_DEFAULT);
8305 mDispatcher->notifyMotion(&motionArgs);
8306 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8307 window->assertNoEvents();
8308}
8309
Antonio Kantekf16f2832021-09-28 04:39:20 +00008310class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8311protected:
8312 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008313 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008314 sp<FakeWindowHandle> mWindow;
8315 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008316 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008317
8318 void SetUp() override {
8319 InputDispatcherTest::SetUp();
8320
8321 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008322 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008323 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008324 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008325 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008326 mSecondWindow =
8327 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008328 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008329 mThirdWindow =
8330 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8331 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8332 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008333
8334 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008335 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8336 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8337 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008338 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008339
Antonio Kantek15beb512022-06-13 22:35:41 +00008340 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008341 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008342 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008343 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8344 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008345 mThirdWindow->assertNoEvents();
8346 }
8347
8348 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8349 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008350 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008351 SECOND_DISPLAY_ID)) {
8352 mWindow->assertNoEvents();
8353 mSecondWindow->assertNoEvents();
8354 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008355 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008356 }
8357
Antonio Kantek15beb512022-06-13 22:35:41 +00008358 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid,
8359 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008360 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8361 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008362 mWindow->consumeTouchModeEvent(inTouchMode);
8363 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008364 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008365 }
8366};
8367
Antonio Kantek26defcf2022-02-08 01:12:27 +00008368TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008369 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008370 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8371 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008372 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008373}
8374
Antonio Kantek26defcf2022-02-08 01:12:27 +00008375TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8376 const WindowInfo& windowInfo = *mWindow->getInfo();
8377 int32_t ownerPid = windowInfo.ownerPid;
8378 int32_t ownerUid = windowInfo.ownerUid;
8379 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
8380 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008381 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008382 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008383 mWindow->assertNoEvents();
8384 mSecondWindow->assertNoEvents();
8385}
8386
8387TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8388 const WindowInfo& windowInfo = *mWindow->getInfo();
8389 int32_t ownerPid = windowInfo.ownerPid;
8390 int32_t ownerUid = windowInfo.ownerUid;
8391 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
Antonio Kantek15beb512022-06-13 22:35:41 +00008392 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008393 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008394}
8395
Antonio Kantekf16f2832021-09-28 04:39:20 +00008396TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008397 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008398 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8399 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008400 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008401 mWindow->assertNoEvents();
8402 mSecondWindow->assertNoEvents();
8403}
8404
Antonio Kantek15beb512022-06-13 22:35:41 +00008405TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8406 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8407 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8408 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008409 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008410 mWindow->assertNoEvents();
8411 mSecondWindow->assertNoEvents();
8412 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8413}
8414
Antonio Kantek48710e42022-03-24 14:19:30 -07008415TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8416 // Interact with the window first.
8417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8418 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8419 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8420
8421 // Then remove focus.
8422 mWindow->setFocusable(false);
8423 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8424
8425 // Assert that caller can switch touch mode by owning one of the last interacted window.
8426 const WindowInfo& windowInfo = *mWindow->getInfo();
8427 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8428 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008429 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008430}
8431
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008432class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8433public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008434 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008435 std::shared_ptr<FakeApplicationHandle> application =
8436 std::make_shared<FakeApplicationHandle>();
8437 std::string name = "Fake Spy ";
8438 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008439 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8440 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008441 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008442 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008443 return spy;
8444 }
8445
8446 sp<FakeWindowHandle> createForeground() {
8447 std::shared_ptr<FakeApplicationHandle> application =
8448 std::make_shared<FakeApplicationHandle>();
8449 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008450 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8451 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008452 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008453 return window;
8454 }
8455
8456private:
8457 int mSpyCount{0};
8458};
8459
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008460using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008461/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008462 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8463 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008464TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8465 ScopedSilentDeath _silentDeath;
8466
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008467 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008468 spy->setTrustedOverlay(false);
8469 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8470 ".* not a trusted overlay");
8471}
8472
8473/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008474 * Input injection into a display with a spy window but no foreground windows should succeed.
8475 */
8476TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008477 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008478 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
8479
8480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8481 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8482 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8483 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8484}
8485
8486/**
8487 * Verify the order in which different input windows receive events. The touched foreground window
8488 * (if there is one) should always receive the event first. When there are multiple spy windows, the
8489 * spy windows will receive the event according to their Z-order, where the top-most spy window will
8490 * receive events before ones belows it.
8491 *
8492 * Here, we set up a scenario with four windows in the following Z order from the top:
8493 * spy1, spy2, window, spy3.
8494 * We then inject an event and verify that the foreground "window" receives it first, followed by
8495 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
8496 * window.
8497 */
8498TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
8499 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008500 auto spy1 = createSpy();
8501 auto spy2 = createSpy();
8502 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008503 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
8504 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
8505 const size_t numChannels = channels.size();
8506
Michael Wright8e9a8562022-02-09 13:44:29 +00008507 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008508 if (!epollFd.ok()) {
8509 FAIL() << "Failed to create epoll fd";
8510 }
8511
8512 for (size_t i = 0; i < numChannels; i++) {
8513 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
8514 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
8515 FAIL() << "Failed to add fd to epoll";
8516 }
8517 }
8518
8519 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8520 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8521 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8522
8523 std::vector<size_t> eventOrder;
8524 std::vector<struct epoll_event> events(numChannels);
8525 for (;;) {
8526 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
8527 (100ms).count());
8528 if (nFds < 0) {
8529 FAIL() << "Failed to call epoll_wait";
8530 }
8531 if (nFds == 0) {
8532 break; // epoll_wait timed out
8533 }
8534 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07008535 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07008536 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008537 channels[i]->consumeMotionDown();
8538 }
8539 }
8540
8541 // Verify the order in which the events were received.
8542 EXPECT_EQ(3u, eventOrder.size());
8543 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
8544 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
8545 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
8546}
8547
8548/**
8549 * A spy window using the NOT_TOUCHABLE flag does not receive events.
8550 */
8551TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
8552 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008553 auto spy = createSpy();
8554 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008555 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8556
8557 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8558 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8559 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8560 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8561 spy->assertNoEvents();
8562}
8563
8564/**
8565 * A spy window will only receive gestures that originate within its touchable region. Gestures that
8566 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
8567 * to the window.
8568 */
8569TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
8570 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008571 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008572 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
8573 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8574
8575 // Inject an event outside the spy window's touchable region.
8576 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8577 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8578 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8579 window->consumeMotionDown();
8580 spy->assertNoEvents();
8581 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8582 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8583 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8584 window->consumeMotionUp();
8585 spy->assertNoEvents();
8586
8587 // Inject an event inside the spy window's touchable region.
8588 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8589 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8590 {5, 10}))
8591 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8592 window->consumeMotionDown();
8593 spy->consumeMotionDown();
8594}
8595
8596/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008597 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008598 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008599 */
8600TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
8601 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008602 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008603 auto spy = createSpy();
8604 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008605 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008606 spy->setFrame(Rect{0, 0, 20, 20});
8607 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8608
8609 // Inject an event outside the spy window's frame and touchable region.
8610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008611 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8612 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008613 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8614 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008615 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008616}
8617
8618/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008619 * Even when a spy window spans over multiple foreground windows, the spy should receive all
8620 * pointers that are down within its bounds.
8621 */
8622TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
8623 auto windowLeft = createForeground();
8624 windowLeft->setFrame({0, 0, 100, 200});
8625 auto windowRight = createForeground();
8626 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008627 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008628 spy->setFrame({0, 0, 200, 200});
8629 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
8630
8631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8632 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8633 {50, 50}))
8634 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8635 windowLeft->consumeMotionDown();
8636 spy->consumeMotionDown();
8637
8638 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008639 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008640 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008641 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
8642 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008643 .build();
8644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8645 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8646 InputEventInjectionSync::WAIT_FOR_RESULT))
8647 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8648 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00008649 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008650}
8651
8652/**
8653 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
8654 * the spy should receive the second pointer with ACTION_DOWN.
8655 */
8656TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
8657 auto window = createForeground();
8658 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008659 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008660 spyRight->setFrame({100, 0, 200, 200});
8661 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
8662
8663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8664 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8665 {50, 50}))
8666 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8667 window->consumeMotionDown();
8668 spyRight->assertNoEvents();
8669
8670 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008671 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008672 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008673 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
8674 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008675 .build();
8676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8677 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8678 InputEventInjectionSync::WAIT_FOR_RESULT))
8679 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008680 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008681 spyRight->consumeMotionDown();
8682}
8683
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008684/**
8685 * The spy window should not be able to affect whether or not touches are split. Only the foreground
8686 * windows should be allowed to control split touch.
8687 */
8688TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008689 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008690 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008691 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008692 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008693
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008694 auto window = createForeground();
8695 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008696
8697 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8698
8699 // First finger down, no window touched.
8700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8701 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8702 {100, 200}))
8703 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8704 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8705 window->assertNoEvents();
8706
8707 // Second finger down on window, the window should receive touch down.
8708 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008709 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008710 .displayId(ADISPLAY_ID_DEFAULT)
8711 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008712 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(200))
8713 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008714 .build();
8715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8716 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8717 InputEventInjectionSync::WAIT_FOR_RESULT))
8718 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8719
8720 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00008721 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008722}
8723
8724/**
8725 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
8726 * do not receive key events.
8727 */
8728TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008729 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008730 spy->setFocusable(false);
8731
8732 auto window = createForeground();
8733 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8734 setFocusedWindow(window);
8735 window->consumeFocusEvent(true);
8736
8737 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
8738 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8739 window->consumeKeyDown(ADISPLAY_ID_NONE);
8740
8741 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
8742 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8743 window->consumeKeyUp(ADISPLAY_ID_NONE);
8744
8745 spy->assertNoEvents();
8746}
8747
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008748using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
8749
8750/**
8751 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
8752 * are currently sent to any other windows - including other spy windows - will also be cancelled.
8753 */
8754TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
8755 auto window = createForeground();
8756 auto spy1 = createSpy();
8757 auto spy2 = createSpy();
8758 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
8759
8760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8761 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8762 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8763 window->consumeMotionDown();
8764 spy1->consumeMotionDown();
8765 spy2->consumeMotionDown();
8766
8767 // Pilfer pointers from the second spy window.
8768 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
8769 spy2->assertNoEvents();
8770 spy1->consumeMotionCancel();
8771 window->consumeMotionCancel();
8772
8773 // The rest of the gesture should only be sent to the second spy window.
8774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8775 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8776 ADISPLAY_ID_DEFAULT))
8777 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8778 spy2->consumeMotionMove();
8779 spy1->assertNoEvents();
8780 window->assertNoEvents();
8781}
8782
8783/**
8784 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
8785 * in the middle of the gesture.
8786 */
8787TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
8788 auto window = createForeground();
8789 auto spy = createSpy();
8790 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8791
8792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8793 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8794 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8795 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8796 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8797
8798 window->releaseChannel();
8799
8800 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8801
8802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8803 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8804 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8805 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8806}
8807
8808/**
8809 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
8810 * the spy, but not to any other windows.
8811 */
8812TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
8813 auto spy = createSpy();
8814 auto window = createForeground();
8815
8816 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8817
8818 // First finger down on the window and the spy.
8819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8820 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8821 {100, 200}))
8822 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8823 spy->consumeMotionDown();
8824 window->consumeMotionDown();
8825
8826 // Spy window pilfers the pointers.
8827 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8828 window->consumeMotionCancel();
8829
8830 // Second finger down on the window and spy, but the window should not receive the pointer down.
8831 const MotionEvent secondFingerDownEvent =
8832 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8833 .displayId(ADISPLAY_ID_DEFAULT)
8834 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008835 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(200))
8836 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008837 .build();
8838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8839 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8840 InputEventInjectionSync::WAIT_FOR_RESULT))
8841 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8842
Harry Cutts33476232023-01-30 19:57:29 +00008843 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008844
8845 // Third finger goes down outside all windows, so injection should fail.
8846 const MotionEvent thirdFingerDownEvent =
8847 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8848 .displayId(ADISPLAY_ID_DEFAULT)
8849 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008850 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(200))
8851 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
8852 .pointer(PointerBuilder(/*id=*/2, AMOTION_EVENT_TOOL_TYPE_FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008853 .build();
8854 ASSERT_EQ(InputEventInjectionResult::FAILED,
8855 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
8856 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008857 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008858
8859 spy->assertNoEvents();
8860 window->assertNoEvents();
8861}
8862
8863/**
8864 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
8865 */
8866TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
8867 auto spy = createSpy();
8868 spy->setFrame(Rect(0, 0, 100, 100));
8869 auto window = createForeground();
8870 window->setFrame(Rect(0, 0, 200, 200));
8871
8872 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8873
8874 // First finger down on the window only
8875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8876 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8877 {150, 150}))
8878 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8879 window->consumeMotionDown();
8880
8881 // Second finger down on the spy and window
8882 const MotionEvent secondFingerDownEvent =
8883 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8884 .displayId(ADISPLAY_ID_DEFAULT)
8885 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008886 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(150))
8887 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008888 .build();
8889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8890 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8891 InputEventInjectionSync::WAIT_FOR_RESULT))
8892 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8893 spy->consumeMotionDown();
8894 window->consumeMotionPointerDown(1);
8895
8896 // Third finger down on the spy and window
8897 const MotionEvent thirdFingerDownEvent =
8898 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8899 .displayId(ADISPLAY_ID_DEFAULT)
8900 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008901 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(150))
8902 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
8903 .pointer(PointerBuilder(/*id=*/2, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008904 .build();
8905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8906 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
8907 InputEventInjectionSync::WAIT_FOR_RESULT))
8908 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8909 spy->consumeMotionPointerDown(1);
8910 window->consumeMotionPointerDown(2);
8911
8912 // Spy window pilfers the pointers.
8913 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8914 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
8915 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
8916
8917 spy->assertNoEvents();
8918 window->assertNoEvents();
8919}
8920
8921/**
8922 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
8923 * other windows should be canceled. If this results in the cancellation of all pointers for some
8924 * window, then that window should receive ACTION_CANCEL.
8925 */
8926TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
8927 auto spy = createSpy();
8928 spy->setFrame(Rect(0, 0, 100, 100));
8929 auto window = createForeground();
8930 window->setFrame(Rect(0, 0, 200, 200));
8931
8932 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8933
8934 // First finger down on both spy and window
8935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8936 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8937 {10, 10}))
8938 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8939 window->consumeMotionDown();
8940 spy->consumeMotionDown();
8941
8942 // Second finger down on the spy and window
8943 const MotionEvent secondFingerDownEvent =
8944 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8945 .displayId(ADISPLAY_ID_DEFAULT)
8946 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008947 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
8948 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008949 .build();
8950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8951 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8952 InputEventInjectionSync::WAIT_FOR_RESULT))
8953 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8954 spy->consumeMotionPointerDown(1);
8955 window->consumeMotionPointerDown(1);
8956
8957 // Spy window pilfers the pointers.
8958 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8959 window->consumeMotionCancel();
8960
8961 spy->assertNoEvents();
8962 window->assertNoEvents();
8963}
8964
8965/**
8966 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
8967 * be sent to other windows
8968 */
8969TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
8970 auto spy = createSpy();
8971 spy->setFrame(Rect(0, 0, 100, 100));
8972 auto window = createForeground();
8973 window->setFrame(Rect(0, 0, 200, 200));
8974
8975 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8976
8977 // First finger down on both window and spy
8978 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8979 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8980 {10, 10}))
8981 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8982 window->consumeMotionDown();
8983 spy->consumeMotionDown();
8984
8985 // Spy window pilfers the pointers.
8986 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8987 window->consumeMotionCancel();
8988
8989 // Second finger down on the window only
8990 const MotionEvent secondFingerDownEvent =
8991 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8992 .displayId(ADISPLAY_ID_DEFAULT)
8993 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008994 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
8995 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008996 .build();
8997 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8998 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8999 InputEventInjectionSync::WAIT_FOR_RESULT))
9000 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9001 window->consumeMotionDown();
9002 window->assertNoEvents();
9003
9004 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9005 spy->consumeMotionMove();
9006 spy->assertNoEvents();
9007}
9008
Prabir Pradhand65552b2021-10-07 11:23:50 -07009009class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9010public:
9011 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9012 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9013 std::make_shared<FakeApplicationHandle>();
9014 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009015 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9016 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009017 overlay->setFocusable(false);
9018 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009019 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009020 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009021 overlay->setTrustedOverlay(true);
9022
9023 std::shared_ptr<FakeApplicationHandle> application =
9024 std::make_shared<FakeApplicationHandle>();
9025 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009026 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9027 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009028 window->setFocusable(true);
9029 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009030
9031 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9032 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9033 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009034 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009035 return {std::move(overlay), std::move(window)};
9036 }
9037
9038 void sendFingerEvent(int32_t action) {
9039 NotifyMotionArgs motionArgs =
9040 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9041 ADISPLAY_ID_DEFAULT, {PointF{20, 20}});
9042 mDispatcher->notifyMotion(&motionArgs);
9043 }
9044
9045 void sendStylusEvent(int32_t action) {
9046 NotifyMotionArgs motionArgs =
9047 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9048 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
9049 motionArgs.pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
9050 mDispatcher->notifyMotion(&motionArgs);
9051 }
9052};
9053
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009054using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9055
9056TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
9057 ScopedSilentDeath _silentDeath;
9058
Prabir Pradhand65552b2021-10-07 11:23:50 -07009059 auto [overlay, window] = setupStylusOverlayScenario();
9060 overlay->setTrustedOverlay(false);
9061 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9062 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9063 ".* not a trusted overlay");
9064}
9065
9066TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9067 auto [overlay, window] = setupStylusOverlayScenario();
9068 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9069
9070 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9071 overlay->consumeMotionDown();
9072 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9073 overlay->consumeMotionUp();
9074
9075 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9076 window->consumeMotionDown();
9077 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9078 window->consumeMotionUp();
9079
9080 overlay->assertNoEvents();
9081 window->assertNoEvents();
9082}
9083
9084TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9085 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009086 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009087 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9088
9089 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9090 overlay->consumeMotionDown();
9091 window->consumeMotionDown();
9092 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9093 overlay->consumeMotionUp();
9094 window->consumeMotionUp();
9095
9096 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9097 window->consumeMotionDown();
9098 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9099 window->consumeMotionUp();
9100
9101 overlay->assertNoEvents();
9102 window->assertNoEvents();
9103}
9104
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009105/**
9106 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9107 * The scenario is as follows:
9108 * - The stylus interceptor overlay is configured as a spy window.
9109 * - The stylus interceptor spy receives the start of a new stylus gesture.
9110 * - It pilfers pointers and then configures itself to no longer be a spy.
9111 * - The stylus interceptor continues to receive the rest of the gesture.
9112 */
9113TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9114 auto [overlay, window] = setupStylusOverlayScenario();
9115 overlay->setSpy(true);
9116 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9117
9118 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9119 overlay->consumeMotionDown();
9120 window->consumeMotionDown();
9121
9122 // The interceptor pilfers the pointers.
9123 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9124 window->consumeMotionCancel();
9125
9126 // The interceptor configures itself so that it is no longer a spy.
9127 overlay->setSpy(false);
9128 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9129
9130 // It continues to receive the rest of the stylus gesture.
9131 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9132 overlay->consumeMotionMove();
9133 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9134 overlay->consumeMotionUp();
9135
9136 window->assertNoEvents();
9137}
9138
Prabir Pradhan5735a322022-04-11 17:23:34 +00009139struct User {
9140 int32_t mPid;
9141 int32_t mUid;
9142 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9143 std::unique_ptr<InputDispatcher>& mDispatcher;
9144
9145 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
9146 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9147
9148 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9149 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9150 ADISPLAY_ID_DEFAULT, {100, 200},
9151 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9152 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9153 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9154 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9155 }
9156
9157 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009158 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009159 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009160 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009161 mPolicyFlags);
9162 }
9163
9164 sp<FakeWindowHandle> createWindow() const {
9165 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9166 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009167 sp<FakeWindowHandle> window =
9168 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9169 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009170 window->setOwnerInfo(mPid, mUid);
9171 return window;
9172 }
9173};
9174
9175using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9176
9177TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
9178 auto owner = User(mDispatcher, 10, 11);
9179 auto window = owner.createWindow();
9180 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9181
9182 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9183 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9184 window->consumeMotionDown();
9185
9186 setFocusedWindow(window);
9187 window->consumeFocusEvent(true);
9188
9189 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9190 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9191 window->consumeKeyDown(ADISPLAY_ID_NONE);
9192}
9193
9194TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
9195 auto owner = User(mDispatcher, 10, 11);
9196 auto window = owner.createWindow();
9197 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9198
9199 auto rando = User(mDispatcher, 20, 21);
9200 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9201 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9202
9203 setFocusedWindow(window);
9204 window->consumeFocusEvent(true);
9205
9206 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9207 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9208 window->assertNoEvents();
9209}
9210
9211TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
9212 auto owner = User(mDispatcher, 10, 11);
9213 auto window = owner.createWindow();
9214 auto spy = owner.createWindow();
9215 spy->setSpy(true);
9216 spy->setTrustedOverlay(true);
9217 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9218
9219 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9220 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9221 spy->consumeMotionDown();
9222 window->consumeMotionDown();
9223}
9224
9225TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
9226 auto owner = User(mDispatcher, 10, 11);
9227 auto window = owner.createWindow();
9228
9229 auto rando = User(mDispatcher, 20, 21);
9230 auto randosSpy = rando.createWindow();
9231 randosSpy->setSpy(true);
9232 randosSpy->setTrustedOverlay(true);
9233 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9234
9235 // The event is targeted at owner's window, so injection should succeed, but the spy should
9236 // not receive the event.
9237 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9238 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9239 randosSpy->assertNoEvents();
9240 window->consumeMotionDown();
9241}
9242
9243TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
9244 auto owner = User(mDispatcher, 10, 11);
9245 auto window = owner.createWindow();
9246
9247 auto rando = User(mDispatcher, 20, 21);
9248 auto randosSpy = rando.createWindow();
9249 randosSpy->setSpy(true);
9250 randosSpy->setTrustedOverlay(true);
9251 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9252
9253 // A user that has injection permission can inject into any window.
9254 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9255 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9256 ADISPLAY_ID_DEFAULT));
9257 randosSpy->consumeMotionDown();
9258 window->consumeMotionDown();
9259
9260 setFocusedWindow(randosSpy);
9261 randosSpy->consumeFocusEvent(true);
9262
9263 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9264 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9265 window->assertNoEvents();
9266}
9267
9268TEST_F(InputDispatcherTargetedInjectionTest, CanGenerateActionOutsideToOtherUids) {
9269 auto owner = User(mDispatcher, 10, 11);
9270 auto window = owner.createWindow();
9271
9272 auto rando = User(mDispatcher, 20, 21);
9273 auto randosWindow = rando.createWindow();
9274 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9275 randosWindow->setWatchOutsideTouch(true);
9276 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9277
9278 // We allow generation of ACTION_OUTSIDE events into windows owned by different uids.
9279 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9280 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9281 window->consumeMotionDown();
9282 randosWindow->consumeMotionOutside();
9283}
9284
Garfield Tane84e6f92019-08-29 17:28:41 -07009285} // namespace android::inputdispatcher