blob: 41c4d6994603cf7f02a0690b56820bd9a11e7744 [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;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070065static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080066static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080067static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080068static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080069/**
70 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
71 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
72 * index 0) is the new pointer going down. The same pointer could have been placed at a different
73 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
74 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
75 * pointer id=0 leaves but the pointer id=1 remains.
76 */
77static constexpr int32_t POINTER_0_DOWN =
78 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080079static constexpr int32_t POINTER_1_DOWN =
80 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000081static constexpr int32_t POINTER_2_DOWN =
82 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000083static constexpr int32_t POINTER_3_DOWN =
84 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000085static constexpr int32_t POINTER_0_UP =
86 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080087static constexpr int32_t POINTER_1_UP =
88 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
89
Antonio Kantek15beb512022-06-13 22:35:41 +000090// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhan5735a322022-04-11 17:23:34 +000091static constexpr int32_t WINDOW_PID = 999;
92static constexpr int32_t WINDOW_UID = 1001;
93
Antonio Kantek15beb512022-06-13 22:35:41 +000094// The default pid and uid for the windows created on the secondary display by the test.
95static constexpr int32_t SECONDARY_WINDOW_PID = 1010;
96static constexpr int32_t SECONDARY_WINDOW_UID = 1012;
97
Prabir Pradhan5735a322022-04-11 17:23:34 +000098// The default policy flags to use for event injection by tests.
99static constexpr uint32_t DEFAULT_POLICY_FLAGS = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800100
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000101// An arbitrary pid of the gesture monitor window
102static constexpr int32_t MONITOR_PID = 2001;
103
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800104static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
105
Arthur Hungc539dbb2022-12-08 07:45:36 +0000106static constexpr int expectedWallpaperFlags =
107 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
108
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800109using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
110
chaviwd1c23182019-12-20 18:44:56 -0800111struct PointF {
112 float x;
113 float y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800114 auto operator<=>(const PointF&) const = default;
chaviwd1c23182019-12-20 18:44:56 -0800115};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800116
Gang Wang342c9272020-01-13 13:15:04 -0500117/**
118 * Return a DOWN key event with KEYCODE_A.
119 */
120static KeyEvent getTestKeyEvent() {
121 KeyEvent event;
122
Garfield Tanfbe732e2020-01-24 11:26:14 -0800123 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
124 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
125 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500126 return event;
127}
128
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000129static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
130 ASSERT_EQ(expectedAction, receivedAction)
131 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
132 << MotionEvent::actionToString(receivedAction);
133}
134
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800135MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") {
136 bool matches = action == arg.getAction();
137 if (!matches) {
138 *result_listener << "expected action " << MotionEvent::actionToString(action)
139 << ", but got " << MotionEvent::actionToString(arg.getAction());
140 }
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800141 if (action == AMOTION_EVENT_ACTION_DOWN) {
142 if (!matches) {
143 *result_listener << "; ";
144 }
145 *result_listener << "downTime should match eventTime for ACTION_DOWN events";
146 matches &= arg.getDownTime() == arg.getEventTime();
147 }
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800148 if (action == AMOTION_EVENT_ACTION_CANCEL) {
149 if (!matches) {
150 *result_listener << "; ";
151 }
152 *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set";
153 matches &= (arg.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
154 }
155 return matches;
156}
157
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800158MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
159 return arg.getDownTime() == downTime;
160}
161
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800162MATCHER_P(WithDisplayId, displayId, "InputEvent with specified displayId") {
163 return arg.getDisplayId() == displayId;
164}
165
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800166MATCHER_P(WithDeviceId, deviceId, "InputEvent with specified deviceId") {
167 return arg.getDeviceId() == deviceId;
168}
169
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800170MATCHER_P(WithSource, source, "InputEvent with specified source") {
171 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
172 << inputEventSourceToString(arg.getSource());
173 return arg.getSource() == source;
174}
175
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800176MATCHER_P(WithFlags, flags, "InputEvent with specified flags") {
177 return arg.getFlags() == flags;
178}
179
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800180MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
181 if (arg.getPointerCount() != 1) {
182 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
183 return false;
184 }
Harry Cutts33476232023-01-30 19:57:29 +0000185 return arg.getX(/*pointerIndex=*/0) == x && arg.getY(/*pointerIndex=*/0) == y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800186}
187
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800188MATCHER_P(WithPointerCount, pointerCount, "MotionEvent with specified number of pointers") {
189 return arg.getPointerCount() == pointerCount;
190}
191
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800192MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
193 // Build a map for the received pointers, by pointer id
194 std::map<int32_t /*pointerId*/, PointF> actualPointers;
195 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
196 const int32_t pointerId = arg.getPointerId(pointerIndex);
197 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
198 }
199 return pointers == actualPointers;
200}
201
Michael Wrightd02c5b62014-02-10 15:10:22 -0800202// --- FakeInputDispatcherPolicy ---
203
204class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
205 InputDispatcherConfiguration mConfig;
206
Prabir Pradhanedd96402022-02-15 01:46:16 -0800207 using AnrResult = std::pair<sp<IBinder>, int32_t /*pid*/>;
208
Michael Wrightd02c5b62014-02-10 15:10:22 -0800209public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000210 FakeInputDispatcherPolicy() = default;
211 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800212
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800213 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700214 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700215 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700216 EXPECT_EQ(event.getDisplayId(), args.displayId);
217
218 const auto& keyEvent = static_cast<const KeyEvent&>(event);
219 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
220 EXPECT_EQ(keyEvent.getAction(), args.action);
221 });
Jackal Guof9696682018-10-05 12:23:23 +0800222 }
223
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700224 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
225 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700226 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700227 EXPECT_EQ(event.getDisplayId(), args.displayId);
228
229 const auto& motionEvent = static_cast<const MotionEvent&>(event);
230 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
231 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000232 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
233 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
234 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
235 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700236 });
Jackal Guof9696682018-10-05 12:23:23 +0800237 }
238
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700239 void assertFilterInputEventWasNotCalled() {
240 std::scoped_lock lock(mLock);
241 ASSERT_EQ(nullptr, mFilteredEvent);
242 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800243
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800244 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700245 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800246 ASSERT_TRUE(mConfigurationChangedTime)
247 << "Timed out waiting for configuration changed call";
248 ASSERT_EQ(*mConfigurationChangedTime, when);
249 mConfigurationChangedTime = std::nullopt;
250 }
251
252 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700253 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800254 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800255 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800256 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
257 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
258 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
259 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
260 mLastNotifySwitch = std::nullopt;
261 }
262
chaviwfd6d3512019-03-25 13:23:49 -0700263 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700264 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800265 ASSERT_EQ(touchedToken, mOnPointerDownToken);
266 mOnPointerDownToken.clear();
267 }
268
269 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700270 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800271 ASSERT_TRUE(mOnPointerDownToken == nullptr)
272 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700273 }
274
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700275 // This function must be called soon after the expected ANR timer starts,
276 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500277 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700278 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500279 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800280 std::unique_lock lock(mLock);
281 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500282 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800283 ASSERT_NO_FATAL_FAILURE(
284 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500285 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700286 }
287
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000288 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800289 const sp<WindowInfoHandle>& window) {
290 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
291 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
292 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500293 }
294
Prabir Pradhanedd96402022-02-15 01:46:16 -0800295 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
296 const sp<IBinder>& expectedToken,
297 int32_t expectedPid) {
298 std::unique_lock lock(mLock);
299 android::base::ScopedLockAssertion assumeLocked(mLock);
300 AnrResult result;
301 ASSERT_NO_FATAL_FAILURE(result =
302 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
303 const auto& [token, pid] = result;
304 ASSERT_EQ(expectedToken, token);
305 ASSERT_EQ(expectedPid, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500306 }
307
Prabir Pradhanedd96402022-02-15 01:46:16 -0800308 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000309 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500310 std::unique_lock lock(mLock);
311 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800312 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
313 const auto& [token, _] = result;
314 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000315 }
316
Prabir Pradhanedd96402022-02-15 01:46:16 -0800317 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
318 int32_t expectedPid) {
319 std::unique_lock lock(mLock);
320 android::base::ScopedLockAssertion assumeLocked(mLock);
321 AnrResult result;
322 ASSERT_NO_FATAL_FAILURE(
323 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
324 const auto& [token, pid] = result;
325 ASSERT_EQ(expectedToken, token);
326 ASSERT_EQ(expectedPid, pid);
327 }
328
329 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000330 sp<IBinder> getResponsiveWindowToken() {
331 std::unique_lock lock(mLock);
332 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800333 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
334 const auto& [token, _] = result;
335 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700336 }
337
338 void assertNotifyAnrWasNotCalled() {
339 std::scoped_lock lock(mLock);
340 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800341 ASSERT_TRUE(mAnrWindows.empty());
342 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500343 << "ANR was not called, but please also consume the 'connection is responsive' "
344 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700345 }
346
Garfield Tan1c7bc862020-01-28 13:24:04 -0800347 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
348 mConfig.keyRepeatTimeout = timeout;
349 mConfig.keyRepeatDelay = delay;
350 }
351
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000352 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800353 std::unique_lock lock(mLock);
354 base::ScopedLockAssertion assumeLocked(mLock);
355
356 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
357 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000358 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800359 enabled;
360 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000361 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
362 << ") to be called.";
363 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800364 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000365 auto request = *mPointerCaptureRequest;
366 mPointerCaptureRequest.reset();
367 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800368 }
369
370 void assertSetPointerCaptureNotCalled() {
371 std::unique_lock lock(mLock);
372 base::ScopedLockAssertion assumeLocked(mLock);
373
374 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000375 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800376 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000377 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800378 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000379 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800380 }
381
arthurhungf452d0b2021-01-06 00:19:52 +0800382 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
383 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800384 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800385 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800386 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800387 }
388
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800389 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
390 std::unique_lock lock(mLock);
391 base::ScopedLockAssertion assumeLocked(mLock);
392 std::optional<sp<IBinder>> receivedToken =
393 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
394 mNotifyInputChannelBroken);
395 ASSERT_TRUE(receivedToken.has_value());
396 ASSERT_EQ(token, *receivedToken);
397 }
398
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800399 /**
400 * Set policy timeout. A value of zero means next key will not be intercepted.
401 */
402 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
403 mInterceptKeyTimeout = timeout;
404 }
405
Josep del Riob3981622023-04-18 15:49:45 +0000406 void assertUserActivityPoked() {
407 std::scoped_lock lock(mLock);
408 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
409 }
410
411 void assertUserActivityNotPoked() {
412 std::scoped_lock lock(mLock);
413 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
414 }
415
Michael Wrightd02c5b62014-02-10 15:10:22 -0800416private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700417 std::mutex mLock;
418 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
419 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
420 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
421 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800422
Prabir Pradhan99987712020-11-10 18:43:05 -0800423 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000424
425 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800426
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700427 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700428 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800429 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
430 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700431 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800432 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
433 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700434
arthurhungf452d0b2021-01-06 00:19:52 +0800435 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800436 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000437 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800438
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800439 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
440
Prabir Pradhanedd96402022-02-15 01:46:16 -0800441 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
442 // for a specific container to become non-empty. When the container is non-empty, return the
443 // first entry from the container and erase it.
444 template <class T>
445 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
446 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
447 // If there is an ANR, Dispatcher won't be idle because there are still events
448 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
449 // before checking if ANR was called.
450 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
451 // to provide it some time to act. 100ms seems reasonable.
452 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
453 const std::chrono::time_point start = std::chrono::steady_clock::now();
454 std::optional<T> token =
455 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
456 if (!token.has_value()) {
457 ADD_FAILURE() << "Did not receive the ANR callback";
458 return {};
459 }
460
461 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
462 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
463 // the dispatcher started counting before this function was called
464 if (std::chrono::abs(timeout - waited) > 100ms) {
465 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
466 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
467 << "ms, but waited "
468 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
469 << "ms instead";
470 }
471 return *token;
472 }
473
474 template <class T>
475 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
476 std::queue<T>& storage,
477 std::unique_lock<std::mutex>& lock,
478 std::condition_variable& condition)
479 REQUIRES(mLock) {
480 condition.wait_for(lock, timeout,
481 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
482 if (storage.empty()) {
483 ADD_FAILURE() << "Did not receive the expected callback";
484 return std::nullopt;
485 }
486 T item = storage.front();
487 storage.pop();
488 return std::make_optional(item);
489 }
490
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600491 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700492 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800493 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800494 }
495
Prabir Pradhanedd96402022-02-15 01:46:16 -0800496 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
497 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700498 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800499 ASSERT_TRUE(pid.has_value());
500 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700501 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500502 }
503
Prabir Pradhanedd96402022-02-15 01:46:16 -0800504 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
505 std::optional<int32_t> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500506 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800507 ASSERT_TRUE(pid.has_value());
508 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500509 mNotifyAnr.notify_all();
510 }
511
512 void notifyNoFocusedWindowAnr(
513 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
514 std::scoped_lock lock(mLock);
515 mAnrApplications.push(applicationHandle);
516 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800517 }
518
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800519 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
520 std::scoped_lock lock(mLock);
521 mBrokenInputChannels.push(connectionToken);
522 mNotifyInputChannelBroken.notify_all();
523 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800524
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600525 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700526
Chris Yef59a2f42020-10-16 12:55:26 -0700527 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
528 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
529 const std::vector<float>& values) override {}
530
531 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
532 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000533
Chris Yefb552902021-02-03 17:18:37 -0800534 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
535
Prabir Pradhana41d2442023-04-20 21:30:40 +0000536 InputDispatcherConfiguration getDispatcherConfiguration() override { return mConfig; }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800537
Prabir Pradhana41d2442023-04-20 21:30:40 +0000538 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700539 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000540 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700541 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000542 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
543 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800544 break;
545 }
546
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700547 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000548 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
549 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800550 break;
551 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700552 default: {
553 ADD_FAILURE() << "Should only filter keys or motions";
554 break;
555 }
Jackal Guof9696682018-10-05 12:23:23 +0800556 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800557 return true;
558 }
559
Prabir Pradhana41d2442023-04-20 21:30:40 +0000560 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
561 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800562 // Clear intercept state when we handled the event.
563 mInterceptKeyTimeout = 0ms;
564 }
565 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800566
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600567 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800568
Prabir Pradhana41d2442023-04-20 21:30:40 +0000569 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800570 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
571 // Clear intercept state so we could dispatch the event in next wake.
572 mInterceptKeyTimeout = 0ms;
573 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800574 }
575
Prabir Pradhana41d2442023-04-20 21:30:40 +0000576 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
577 uint32_t) override {
578 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800579 }
580
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600581 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
582 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700583 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800584 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
585 * essentially a passthrough for notifySwitch.
586 */
Harry Cutts33476232023-01-30 19:57:29 +0000587 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800588 }
589
Josep del Riob3981622023-04-18 15:49:45 +0000590 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
591 std::scoped_lock lock(mLock);
592 mPokedUserActivity = true;
593 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800594
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600595 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700596 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700597 mOnPointerDownToken = newToken;
598 }
599
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000600 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800601 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000602 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800603 mPointerCaptureChangedCondition.notify_all();
604 }
605
arthurhungf452d0b2021-01-06 00:19:52 +0800606 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
607 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800608 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800609 mDropTargetWindowToken = token;
610 }
611
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700612 void assertFilterInputEventWasCalledInternal(
613 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700614 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800615 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700616 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800617 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800618 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800619};
620
Michael Wrightd02c5b62014-02-10 15:10:22 -0800621// --- InputDispatcherTest ---
622
623class InputDispatcherTest : public testing::Test {
624protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000625 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700626 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800627
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000628 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000629 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
630 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800631 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000632 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700633 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800634 }
635
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000636 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700637 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000638 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700639 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800640 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700641
642 /**
643 * Used for debugging when writing the test
644 */
645 void dumpDispatcherState() {
646 std::string dump;
647 mDispatcher->dump(dump);
648 std::stringstream ss(dump);
649 std::string to;
650
651 while (std::getline(ss, to, '\n')) {
652 ALOGE("%s", to.c_str());
653 }
654 }
Vishnu Nair958da932020-08-21 17:12:37 -0700655
Chavi Weingarten847e8512023-03-29 00:26:09 +0000656 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700657 FocusRequest request;
658 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000659 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700660 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
661 request.displayId = window->getInfo()->displayId;
662 mDispatcher->setFocusedWindow(request);
663 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800664};
665
Michael Wrightd02c5b62014-02-10 15:10:22 -0800666TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
667 KeyEvent event;
668
669 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800670 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
671 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600672 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
673 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800674 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000675 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000676 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800677 << "Should reject key events with undefined action.";
678
679 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800680 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
681 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600682 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800683 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000684 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000685 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800686 << "Should reject key events with ACTION_MULTIPLE.";
687}
688
689TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
690 MotionEvent event;
691 PointerProperties pointerProperties[MAX_POINTERS + 1];
692 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800693 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800694 pointerProperties[i].clear();
695 pointerProperties[i].id = i;
696 pointerCoords[i].clear();
697 }
698
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800699 // Some constants commonly used below
700 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
701 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
702 constexpr int32_t metaState = AMETA_NONE;
703 constexpr MotionClassification classification = MotionClassification::NONE;
704
chaviw9eaa22c2020-07-01 16:21:27 -0700705 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800706 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800707 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700708 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
709 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700710 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
711 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700712 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800713 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000714 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000715 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800716 << "Should reject motion events with undefined action.";
717
718 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800719 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800720 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
721 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
722 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
723 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500724 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800725 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000726 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000727 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800728 << "Should reject motion events with pointer down index too large.";
729
Garfield Tanfbe732e2020-01-24 11:26:14 -0800730 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700731 AMOTION_EVENT_ACTION_POINTER_DOWN |
732 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700733 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
734 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700735 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500736 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800737 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000738 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000739 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800740 << "Should reject motion events with pointer down index too small.";
741
742 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800743 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800744 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
745 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
746 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
747 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500748 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800749 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000750 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000751 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800752 << "Should reject motion events with pointer up index too large.";
753
Garfield Tanfbe732e2020-01-24 11:26:14 -0800754 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700755 AMOTION_EVENT_ACTION_POINTER_UP |
756 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700757 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
758 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700759 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500760 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800761 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000762 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000763 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800764 << "Should reject motion events with pointer up index too small.";
765
766 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800767 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
768 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700769 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700770 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
771 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700772 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800773 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000774 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000775 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800776 << "Should reject motion events with 0 pointers.";
777
Garfield Tanfbe732e2020-01-24 11:26:14 -0800778 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
779 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700780 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700781 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
782 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700783 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800784 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000785 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000786 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800787 << "Should reject motion events with more than MAX_POINTERS pointers.";
788
789 // Rejects motion events with invalid pointer ids.
790 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800791 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
792 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700793 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700794 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
795 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700796 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800797 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000798 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000799 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800800 << "Should reject motion events with pointer ids less than 0.";
801
802 pointerProperties[0].id = MAX_POINTER_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*/ 1, 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 pointer ids greater than MAX_POINTER_ID.";
813
814 // Rejects motion events with duplicate pointer ids.
815 pointerProperties[0].id = 1;
816 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800817 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
818 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700819 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700820 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
821 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700822 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800823 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000824 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000825 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800826 << "Should reject motion events with duplicate pointer ids.";
827}
828
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800829/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
830
831TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
832 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000833 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800834 ASSERT_TRUE(mDispatcher->waitForIdle());
835
836 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
837}
838
839TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000840 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
841 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000842 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800843
844 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
845 args.policyFlags |= POLICY_FLAG_TRUSTED;
846 mFakePolicy->assertNotifySwitchWasCalled(args);
847}
848
Arthur Hungb92218b2018-08-14 12:00:21 +0800849// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700850static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700851// Default input dispatching timeout if there is no focused application or paused window
852// from which to determine an appropriate dispatching timeout.
853static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
854 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
855 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800856
857class FakeApplicationHandle : public InputApplicationHandle {
858public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700859 FakeApplicationHandle() {
860 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700861 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500862 mInfo.dispatchingTimeoutMillis =
863 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700864 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800865 virtual ~FakeApplicationHandle() {}
866
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000867 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700868
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500869 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
870 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700871 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800872};
873
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800874class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800875public:
Garfield Tan15601662020-09-22 15:32:38 -0700876 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800877 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700878 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800879 }
880
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800881 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700882 InputEvent* event;
883 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
884 if (!consumeSeq) {
885 return nullptr;
886 }
887 finishEvent(*consumeSeq);
888 return event;
889 }
890
891 /**
892 * Receive an event without acknowledging it.
893 * Return the sequence number that could later be used to send finished signal.
894 */
895 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800896 uint32_t consumeSeq;
897 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800898
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800899 std::chrono::time_point start = std::chrono::steady_clock::now();
900 status_t status = WOULD_BLOCK;
901 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000902 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800903 &event);
904 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
905 if (elapsed > 100ms) {
906 break;
907 }
908 }
909
910 if (status == WOULD_BLOCK) {
911 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700912 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800913 }
914
915 if (status != OK) {
916 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700917 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800918 }
919 if (event == nullptr) {
920 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700921 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800922 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700923 if (outEvent != nullptr) {
924 *outEvent = event;
925 }
926 return consumeSeq;
927 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800928
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700929 /**
930 * To be used together with "receiveEvent" to complete the consumption of an event.
931 */
932 void finishEvent(uint32_t consumeSeq) {
933 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
934 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800935 }
936
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000937 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
938 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
939 ASSERT_EQ(OK, status);
940 }
941
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700942 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000943 std::optional<int32_t> expectedDisplayId,
944 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800945 InputEvent* event = consume();
946
947 ASSERT_NE(nullptr, event) << mName.c_str()
948 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800949 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700950 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
951 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800952
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000953 if (expectedDisplayId.has_value()) {
954 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
955 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800956
Tiger Huang8664f8c2018-10-11 19:14:35 +0800957 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700958 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800959 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
960 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000961 if (expectedFlags.has_value()) {
962 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
963 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800964 break;
965 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700966 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800967 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000968 assertMotionAction(expectedAction, motionEvent.getAction());
969
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000970 if (expectedFlags.has_value()) {
971 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
972 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800973 break;
974 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700975 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100976 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
977 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700978 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800979 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
980 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700981 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000982 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
983 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700984 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800985 FAIL() << "Use 'consumeDragEvent' for DRAG events";
986 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800987 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800988 }
989
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800990 MotionEvent* consumeMotion() {
991 InputEvent* event = consume();
992
993 if (event == nullptr) {
994 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
995 return nullptr;
996 }
997
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700998 if (event->getType() != InputEventType::MOTION) {
999 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001000 return nullptr;
1001 }
1002 return static_cast<MotionEvent*>(event);
1003 }
1004
1005 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1006 MotionEvent* motionEvent = consumeMotion();
1007 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1008 ASSERT_THAT(*motionEvent, matcher);
1009 }
1010
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001011 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1012 InputEvent* event = consume();
1013 ASSERT_NE(nullptr, event) << mName.c_str()
1014 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001015 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1016 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001017
1018 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1019 << mName.c_str() << ": event displayId should always be NONE.";
1020
1021 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1022 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001023 }
1024
Prabir Pradhan99987712020-11-10 18:43:05 -08001025 void consumeCaptureEvent(bool hasCapture) {
1026 const InputEvent* event = consume();
1027 ASSERT_NE(nullptr, event) << mName.c_str()
1028 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001029 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1030 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001031
1032 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1033 << mName.c_str() << ": event displayId should always be NONE.";
1034
1035 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1036 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1037 }
1038
arthurhungb89ccb02020-12-30 16:19:01 +08001039 void consumeDragEvent(bool isExiting, float x, float y) {
1040 const InputEvent* event = consume();
1041 ASSERT_NE(nullptr, event) << mName.c_str()
1042 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001043 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001044
1045 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1046 << mName.c_str() << ": event displayId should always be NONE.";
1047
1048 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1049 EXPECT_EQ(isExiting, dragEvent.isExiting());
1050 EXPECT_EQ(x, dragEvent.getX());
1051 EXPECT_EQ(y, dragEvent.getY());
1052 }
1053
Antonio Kantekf16f2832021-09-28 04:39:20 +00001054 void consumeTouchModeEvent(bool inTouchMode) {
1055 const InputEvent* event = consume();
1056 ASSERT_NE(nullptr, event) << mName.c_str()
1057 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001058 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1059 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001060
1061 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1062 << mName.c_str() << ": event displayId should always be NONE.";
1063 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1064 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1065 }
1066
chaviwd1c23182019-12-20 18:44:56 -08001067 void assertNoEvents() {
1068 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001069 if (event == nullptr) {
1070 return;
1071 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001072 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001073 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1074 ADD_FAILURE() << "Received key event "
1075 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001076 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001077 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1078 ADD_FAILURE() << "Received motion event "
1079 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001080 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001081 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1082 ADD_FAILURE() << "Received focus event, hasFocus = "
1083 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001084 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001085 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1086 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1087 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001088 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001089 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1090 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1091 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001092 }
1093 FAIL() << mName.c_str()
1094 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001095 }
1096
1097 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1098
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001099 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1100
chaviwd1c23182019-12-20 18:44:56 -08001101protected:
1102 std::unique_ptr<InputConsumer> mConsumer;
1103 PreallocatedInputEventFactory mEventFactory;
1104
1105 std::string mName;
1106};
1107
chaviw3277faf2021-05-19 16:45:23 -05001108class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001109public:
1110 static const int32_t WIDTH = 600;
1111 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001112
Chris Yea209fde2020-07-22 13:54:51 -07001113 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001114 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001115 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001116 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001117 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001118 base::Result<std::unique_ptr<InputChannel>> channel =
1119 dispatcher->createInputChannel(name);
1120 token = (*channel)->getConnectionToken();
1121 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001122 }
1123
1124 inputApplicationHandle->updateInfo();
1125 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1126
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001127 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001128 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001129 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001130 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001131 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001132 mInfo.frameLeft = 0;
1133 mInfo.frameTop = 0;
1134 mInfo.frameRight = WIDTH;
1135 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001136 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001137 mInfo.globalScaleFactor = 1.0;
1138 mInfo.touchableRegion.clear();
1139 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001140 mInfo.ownerPid = WINDOW_PID;
1141 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001142 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001143 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001144 }
1145
Arthur Hungabbb9d82021-09-01 14:52:30 +00001146 sp<FakeWindowHandle> clone(
1147 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001148 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00001149 sp<FakeWindowHandle> handle =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001150 sp<FakeWindowHandle>::make(inputApplicationHandle, dispatcher,
1151 mInfo.name + "(Mirror)", displayId, mInfo.token);
Arthur Hungabbb9d82021-09-01 14:52:30 +00001152 return handle;
1153 }
1154
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001155 void setTouchable(bool touchable) {
1156 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1157 }
chaviwd1c23182019-12-20 18:44:56 -08001158
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001159 void setFocusable(bool focusable) {
1160 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1161 }
1162
1163 void setVisible(bool visible) {
1164 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1165 }
Vishnu Nair958da932020-08-21 17:12:37 -07001166
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001167 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001168 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001169 }
1170
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001171 void setPaused(bool paused) {
1172 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1173 }
1174
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001175 void setPreventSplitting(bool preventSplitting) {
1176 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001177 }
1178
1179 void setSlippery(bool slippery) {
1180 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1181 }
1182
1183 void setWatchOutsideTouch(bool watchOutside) {
1184 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1185 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001186
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001187 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1188
1189 void setInterceptsStylus(bool interceptsStylus) {
1190 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1191 }
1192
1193 void setDropInput(bool dropInput) {
1194 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1195 }
1196
1197 void setDropInputIfObscured(bool dropInputIfObscured) {
1198 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1199 }
1200
1201 void setNoInputChannel(bool noInputChannel) {
1202 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1203 }
1204
Josep del Riob3981622023-04-18 15:49:45 +00001205 void setDisableUserActivity(bool disableUserActivity) {
1206 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1207 }
1208
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001209 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1210
chaviw3277faf2021-05-19 16:45:23 -05001211 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001212
Bernardo Rufino7393d172021-02-26 13:56:11 +00001213 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1214
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001215 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001216 mInfo.frameLeft = frame.left;
1217 mInfo.frameTop = frame.top;
1218 mInfo.frameRight = frame.right;
1219 mInfo.frameBottom = frame.bottom;
1220 mInfo.touchableRegion.clear();
1221 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001222
1223 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1224 ui::Transform translate;
1225 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1226 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001227 }
1228
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001229 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1230
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001231 void setIsWallpaper(bool isWallpaper) {
1232 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1233 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001234
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001235 void setDupTouchToWallpaper(bool hasWallpaper) {
1236 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1237 }
chaviwd1c23182019-12-20 18:44:56 -08001238
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001239 void setTrustedOverlay(bool trustedOverlay) {
1240 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1241 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001242
chaviw9eaa22c2020-07-01 16:21:27 -07001243 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1244 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1245 }
1246
1247 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001248
yunho.shinf4a80b82020-11-16 21:13:57 +09001249 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1250
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001251 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001252 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001253 }
1254
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001255 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001256 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001257 }
1258
Svet Ganov5d3bc372020-01-26 23:11:07 -08001259 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001260 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001261 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1262 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001263 }
1264
1265 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001266 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001267 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1268 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001269 }
1270
1271 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001272 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001273 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1274 }
1275
1276 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1277 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001278 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001279 expectedFlags);
1280 }
1281
Svet Ganov5d3bc372020-01-26 23:11:07 -08001282 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001283 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1284 int32_t expectedFlags = 0) {
1285 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1286 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001287 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001288 }
1289
1290 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001291 int32_t expectedFlags = 0) {
1292 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1293 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001294 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001295 }
1296
1297 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001298 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001299 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001300 expectedFlags);
1301 }
1302
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001303 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1304 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001305 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001306 expectedFlags);
1307 }
1308
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001309 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1310 int32_t expectedFlags = 0) {
1311 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001312 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001313 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001314 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1315 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1316 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1317 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1318 }
1319
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001320 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1321 ASSERT_NE(mInputReceiver, nullptr)
1322 << "Cannot consume events from a window with no receiver";
1323 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1324 }
1325
Prabir Pradhan99987712020-11-10 18:43:05 -08001326 void consumeCaptureEvent(bool hasCapture) {
1327 ASSERT_NE(mInputReceiver, nullptr)
1328 << "Cannot consume events from a window with no receiver";
1329 mInputReceiver->consumeCaptureEvent(hasCapture);
1330 }
1331
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001332 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1333 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001334 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001335 ASSERT_THAT(*motionEvent, matcher);
1336 }
1337
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001338 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001339 std::optional<int32_t> expectedDisplayId,
1340 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001341 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1342 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1343 expectedFlags);
1344 }
1345
arthurhungb89ccb02020-12-30 16:19:01 +08001346 void consumeDragEvent(bool isExiting, float x, float y) {
1347 mInputReceiver->consumeDragEvent(isExiting, x, y);
1348 }
1349
Antonio Kantekf16f2832021-09-28 04:39:20 +00001350 void consumeTouchModeEvent(bool inTouchMode) {
1351 ASSERT_NE(mInputReceiver, nullptr)
1352 << "Cannot consume events from a window with no receiver";
1353 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1354 }
1355
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001356 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001357 if (mInputReceiver == nullptr) {
1358 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1359 return std::nullopt;
1360 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001361 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001362 }
1363
1364 void finishEvent(uint32_t sequenceNum) {
1365 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1366 mInputReceiver->finishEvent(sequenceNum);
1367 }
1368
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001369 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1370 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1371 mInputReceiver->sendTimeline(inputEventId, timeline);
1372 }
1373
chaviwaf87b3e2019-10-01 16:59:28 -07001374 InputEvent* consume() {
1375 if (mInputReceiver == nullptr) {
1376 return nullptr;
1377 }
1378 return mInputReceiver->consume();
1379 }
1380
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001381 MotionEvent* consumeMotion() {
1382 InputEvent* event = consume();
1383 if (event == nullptr) {
1384 ADD_FAILURE() << "Consume failed : no event";
1385 return nullptr;
1386 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001387 if (event->getType() != InputEventType::MOTION) {
1388 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001389 return nullptr;
1390 }
1391 return static_cast<MotionEvent*>(event);
1392 }
1393
Arthur Hungb92218b2018-08-14 12:00:21 +08001394 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001395 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001396 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001397 return; // Can't receive events if the window does not have input channel
1398 }
1399 ASSERT_NE(nullptr, mInputReceiver)
1400 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001401 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001402 }
1403
chaviwaf87b3e2019-10-01 16:59:28 -07001404 sp<IBinder> getToken() { return mInfo.token; }
1405
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001406 const std::string& getName() { return mName; }
1407
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001408 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1409 mInfo.ownerPid = ownerPid;
1410 mInfo.ownerUid = ownerUid;
1411 }
1412
Prabir Pradhanedd96402022-02-15 01:46:16 -08001413 int32_t getPid() const { return mInfo.ownerPid; }
1414
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001415 void destroyReceiver() { mInputReceiver = nullptr; }
1416
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001417 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1418
chaviwd1c23182019-12-20 18:44:56 -08001419private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001420 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001421 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001422 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001423};
1424
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001425std::atomic<int32_t> FakeWindowHandle::sId{1};
1426
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001427static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001428 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001429 int32_t displayId = ADISPLAY_ID_NONE,
1430 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001431 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001432 bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
1433 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001434 KeyEvent event;
1435 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1436
1437 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001438 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001439 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1440 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001441
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001442 if (!allowKeyRepeat) {
1443 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1444 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001445 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001446 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001447}
1448
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001449static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001450 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001451 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001452}
1453
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001454// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1455// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1456// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001457static InputEventInjectionResult injectKeyDownNoRepeat(
1458 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001459 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001460 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001461 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001462}
1463
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001464static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001465 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001466 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001467}
1468
Garfield Tandf26e862020-07-01 20:18:19 -07001469class PointerBuilder {
1470public:
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001471 PointerBuilder(int32_t id, ToolType toolType) {
Garfield Tandf26e862020-07-01 20:18:19 -07001472 mProperties.clear();
1473 mProperties.id = id;
1474 mProperties.toolType = toolType;
1475 mCoords.clear();
1476 }
1477
1478 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1479
1480 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1481
1482 PointerBuilder& axis(int32_t axis, float value) {
1483 mCoords.setAxisValue(axis, value);
1484 return *this;
1485 }
1486
1487 PointerProperties buildProperties() const { return mProperties; }
1488
1489 PointerCoords buildCoords() const { return mCoords; }
1490
1491private:
1492 PointerProperties mProperties;
1493 PointerCoords mCoords;
1494};
1495
1496class MotionEventBuilder {
1497public:
1498 MotionEventBuilder(int32_t action, int32_t source) {
1499 mAction = action;
1500 mSource = source;
1501 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001502 mDownTime = mEventTime;
Garfield Tandf26e862020-07-01 20:18:19 -07001503 }
1504
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001505 MotionEventBuilder& deviceId(int32_t deviceId) {
1506 mDeviceId = deviceId;
1507 return *this;
1508 }
1509
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001510 MotionEventBuilder& downTime(nsecs_t downTime) {
1511 mDownTime = downTime;
1512 return *this;
1513 }
1514
Garfield Tandf26e862020-07-01 20:18:19 -07001515 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1516 mEventTime = eventTime;
1517 return *this;
1518 }
1519
1520 MotionEventBuilder& displayId(int32_t displayId) {
1521 mDisplayId = displayId;
1522 return *this;
1523 }
1524
1525 MotionEventBuilder& actionButton(int32_t actionButton) {
1526 mActionButton = actionButton;
1527 return *this;
1528 }
1529
arthurhung6d4bed92021-03-17 11:59:33 +08001530 MotionEventBuilder& buttonState(int32_t buttonState) {
1531 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001532 return *this;
1533 }
1534
1535 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1536 mRawXCursorPosition = rawXCursorPosition;
1537 return *this;
1538 }
1539
1540 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1541 mRawYCursorPosition = rawYCursorPosition;
1542 return *this;
1543 }
1544
1545 MotionEventBuilder& pointer(PointerBuilder pointer) {
1546 mPointers.push_back(pointer);
1547 return *this;
1548 }
1549
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001550 MotionEventBuilder& addFlag(uint32_t flags) {
1551 mFlags |= flags;
1552 return *this;
1553 }
1554
Garfield Tandf26e862020-07-01 20:18:19 -07001555 MotionEvent build() {
1556 std::vector<PointerProperties> pointerProperties;
1557 std::vector<PointerCoords> pointerCoords;
1558 for (const PointerBuilder& pointer : mPointers) {
1559 pointerProperties.push_back(pointer.buildProperties());
1560 pointerCoords.push_back(pointer.buildCoords());
1561 }
1562
1563 // Set mouse cursor position for the most common cases to avoid boilerplate.
1564 if (mSource == AINPUT_SOURCE_MOUSE &&
1565 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1566 mPointers.size() == 1) {
1567 mRawXCursorPosition = pointerCoords[0].getX();
1568 mRawYCursorPosition = pointerCoords[0].getY();
1569 }
1570
1571 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001572 ui::Transform identityTransform;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001573 event.initialize(InputEvent::nextId(), mDeviceId, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001574 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001575 mButtonState, MotionClassification::NONE, identityTransform,
1576 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001577 mRawYCursorPosition, identityTransform, mDownTime, mEventTime,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07001578 mPointers.size(), pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001579
1580 return event;
1581 }
1582
1583private:
1584 int32_t mAction;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001585 int32_t mDeviceId = DEVICE_ID;
Garfield Tandf26e862020-07-01 20:18:19 -07001586 int32_t mSource;
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001587 nsecs_t mDownTime;
Garfield Tandf26e862020-07-01 20:18:19 -07001588 nsecs_t mEventTime;
1589 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1590 int32_t mActionButton{0};
1591 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001592 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001593 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1594 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1595
1596 std::vector<PointerBuilder> mPointers;
1597};
1598
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001599class MotionArgsBuilder {
1600public:
1601 MotionArgsBuilder(int32_t action, int32_t source) {
1602 mAction = action;
1603 mSource = source;
1604 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1605 mDownTime = mEventTime;
1606 }
1607
1608 MotionArgsBuilder& deviceId(int32_t deviceId) {
1609 mDeviceId = deviceId;
1610 return *this;
1611 }
1612
1613 MotionArgsBuilder& downTime(nsecs_t downTime) {
1614 mDownTime = downTime;
1615 return *this;
1616 }
1617
1618 MotionArgsBuilder& eventTime(nsecs_t eventTime) {
1619 mEventTime = eventTime;
1620 return *this;
1621 }
1622
1623 MotionArgsBuilder& displayId(int32_t displayId) {
1624 mDisplayId = displayId;
1625 return *this;
1626 }
1627
1628 MotionArgsBuilder& policyFlags(int32_t policyFlags) {
1629 mPolicyFlags = policyFlags;
1630 return *this;
1631 }
1632
1633 MotionArgsBuilder& actionButton(int32_t actionButton) {
1634 mActionButton = actionButton;
1635 return *this;
1636 }
1637
1638 MotionArgsBuilder& buttonState(int32_t buttonState) {
1639 mButtonState = buttonState;
1640 return *this;
1641 }
1642
1643 MotionArgsBuilder& rawXCursorPosition(float rawXCursorPosition) {
1644 mRawXCursorPosition = rawXCursorPosition;
1645 return *this;
1646 }
1647
1648 MotionArgsBuilder& rawYCursorPosition(float rawYCursorPosition) {
1649 mRawYCursorPosition = rawYCursorPosition;
1650 return *this;
1651 }
1652
1653 MotionArgsBuilder& pointer(PointerBuilder pointer) {
1654 mPointers.push_back(pointer);
1655 return *this;
1656 }
1657
1658 MotionArgsBuilder& addFlag(uint32_t flags) {
1659 mFlags |= flags;
1660 return *this;
1661 }
1662
1663 NotifyMotionArgs build() {
1664 std::vector<PointerProperties> pointerProperties;
1665 std::vector<PointerCoords> pointerCoords;
1666 for (const PointerBuilder& pointer : mPointers) {
1667 pointerProperties.push_back(pointer.buildProperties());
1668 pointerCoords.push_back(pointer.buildCoords());
1669 }
1670
1671 // Set mouse cursor position for the most common cases to avoid boilerplate.
1672 if (mSource == AINPUT_SOURCE_MOUSE &&
1673 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1674 mPointers.size() == 1) {
1675 mRawXCursorPosition = pointerCoords[0].getX();
1676 mRawYCursorPosition = pointerCoords[0].getY();
1677 }
1678
1679 NotifyMotionArgs args(InputEvent::nextId(), mEventTime, /*readTime=*/mEventTime, mDeviceId,
1680 mSource, mDisplayId, mPolicyFlags, mAction, mActionButton, mFlags,
1681 AMETA_NONE, mButtonState, MotionClassification::NONE, /*edgeFlags=*/0,
1682 mPointers.size(), pointerProperties.data(), pointerCoords.data(),
1683 /*xPrecision=*/0, /*yPrecision=*/0, mRawXCursorPosition,
1684 mRawYCursorPosition, mDownTime, /*videoFrames=*/{});
1685
1686 return args;
1687 }
1688
1689private:
1690 int32_t mAction;
1691 int32_t mDeviceId = DEVICE_ID;
1692 int32_t mSource;
1693 nsecs_t mDownTime;
1694 nsecs_t mEventTime;
1695 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1696 int32_t mPolicyFlags = DEFAULT_POLICY_FLAGS;
1697 int32_t mActionButton{0};
1698 int32_t mButtonState{0};
1699 int32_t mFlags{0};
1700 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1701 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1702
1703 std::vector<PointerBuilder> mPointers;
1704};
1705
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001706static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001707 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001708 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001709 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1710 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
1711 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1712 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001713}
1714
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001715static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001716 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001717 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001718 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001719 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1720 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001721 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001722 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
1723 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Garfield Tandf26e862020-07-01 20:18:19 -07001724 MotionEvent event = MotionEventBuilder(action, source)
1725 .displayId(displayId)
1726 .eventTime(eventTime)
1727 .rawXCursorPosition(cursorPosition.x)
1728 .rawYCursorPosition(cursorPosition.y)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001729 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Garfield Tandf26e862020-07-01 20:18:19 -07001730 .x(position.x)
1731 .y(position.y))
1732 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001733
1734 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001735 return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode, targetUid,
1736 policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001737}
1738
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001739static InputEventInjectionResult injectMotionDown(
1740 const std::unique_ptr<InputDispatcher>& dispatcher, 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_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001743}
1744
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001745static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001746 int32_t source, int32_t displayId,
1747 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001748 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001749}
1750
Jackal Guof9696682018-10-05 12:23:23 +08001751static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1752 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1753 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001754 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001755 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1756 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001757
1758 return args;
1759}
1760
Josep del Riob3981622023-04-18 15:49:45 +00001761static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1762 int32_t displayId = ADISPLAY_ID_NONE) {
1763 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1764 // Define a valid key event.
1765 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1766 displayId, 0, action, /* flags */ 0, AKEYCODE_C, KEY_C, AMETA_META_ON,
1767 currentTime);
1768
1769 return args;
1770}
1771
1772static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1773 int32_t displayId = ADISPLAY_ID_NONE) {
1774 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1775 // Define a valid key event.
1776 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1777 displayId, 0, action, /* flags */ 0, AKEYCODE_ASSIST, KEY_ASSISTANT,
1778 AMETA_NONE, currentTime);
1779
1780 return args;
1781}
1782
Prabir Pradhan678438e2023-04-13 19:32:51 +00001783[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1784 int32_t displayId,
1785 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001786 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001787 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1788 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1789 }
1790
chaviwd1c23182019-12-20 18:44:56 -08001791 PointerProperties pointerProperties[pointerCount];
1792 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001793
chaviwd1c23182019-12-20 18:44:56 -08001794 for (size_t i = 0; i < pointerCount; i++) {
1795 pointerProperties[i].clear();
1796 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001797 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001798
chaviwd1c23182019-12-20 18:44:56 -08001799 pointerCoords[i].clear();
1800 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1801 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1802 }
Jackal Guof9696682018-10-05 12:23:23 +08001803
1804 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1805 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001806 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001807 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1808 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001809 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1810 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001811 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1812 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001813
1814 return args;
1815}
1816
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001817static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1818 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1819}
1820
chaviwd1c23182019-12-20 18:44:56 -08001821static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1822 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1823}
1824
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001825static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1826 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001827 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001828}
1829
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001830/**
1831 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1832 * broken channel.
1833 */
1834TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1835 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1836 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001837 sp<FakeWindowHandle>::make(application, mDispatcher,
1838 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001839
1840 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1841
1842 // Window closes its channel, but the window remains.
1843 window->destroyReceiver();
1844 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1845}
1846
Arthur Hungb92218b2018-08-14 12:00:21 +08001847TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001848 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001849 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1850 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001851
Arthur Hung72d8dc32020-03-28 00:48:39 +00001852 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1854 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1855 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001856
1857 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001858 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001859}
1860
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001861TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1862 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001863 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1864 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001865
1866 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1867 // Inject a MotionEvent to an unknown display.
1868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1869 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1870 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1871
1872 // Window should receive motion event.
1873 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1874}
1875
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001876/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001877 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001878 * This test serves as a sanity check for the next test, where setInputWindows is
1879 * called twice.
1880 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001881TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001882 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001883 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1884 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001885 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001886
1887 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001889 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1890 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001891 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001892
1893 // Window should receive motion event.
1894 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1895}
1896
1897/**
1898 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001899 */
1900TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001901 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001902 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1903 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001904 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001905
1906 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1907 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001909 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1910 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001911 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001912
1913 // Window should receive motion event.
1914 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1915}
1916
Arthur Hungb92218b2018-08-14 12:00:21 +08001917// The foreground window should receive the first touch down event.
1918TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001919 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001920 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001921 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001922 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001923 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001924
Arthur Hung72d8dc32020-03-28 00:48:39 +00001925 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1927 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1928 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001929
1930 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001931 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001932 windowSecond->assertNoEvents();
1933}
1934
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001935/**
1936 * Two windows: A top window, and a wallpaper behind the window.
1937 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1938 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001939 * 1. foregroundWindow <-- dup touch to wallpaper
1940 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001941 */
1942TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1943 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1944 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001945 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001946 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001947 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001948 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001949 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001950
1951 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1952 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1953 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1954 {100, 200}))
1955 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1956
1957 // Both foreground window and its wallpaper should receive the touch down
1958 foregroundWindow->consumeMotionDown();
1959 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1960
1961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1962 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1963 ADISPLAY_ID_DEFAULT, {110, 200}))
1964 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1965
1966 foregroundWindow->consumeMotionMove();
1967 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1968
1969 // Now the foreground window goes away, but the wallpaper stays
1970 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1971 foregroundWindow->consumeMotionCancel();
1972 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1973 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1974}
1975
1976/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001977 * Two fingers down on the window, and lift off the first finger.
1978 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1979 * contains a single pointer.
1980 */
1981TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1982 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1983 sp<FakeWindowHandle> window =
1984 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1985
1986 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001987 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001988 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1989 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1990 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001991 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001992 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1993 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1994 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1995 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001996 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001997 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1998 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1999 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
2000 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002001 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2002 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2003 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2004
2005 // Remove the window. The gesture should be canceled
2006 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
2007 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
2008 window->consumeMotionEvent(
2009 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
2010}
2011
2012/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002013 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
2014 * with the following differences:
2015 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
2016 * clean up the connection.
2017 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
2018 * Ensure that there's no crash in the dispatcher.
2019 */
2020TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
2021 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2022 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002023 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002024 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002025 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002026 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002027 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002028
2029 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
2030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2031 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2032 {100, 200}))
2033 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2034
2035 // Both foreground window and its wallpaper should receive the touch down
2036 foregroundWindow->consumeMotionDown();
2037 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2038
2039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2040 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2041 ADISPLAY_ID_DEFAULT, {110, 200}))
2042 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2043
2044 foregroundWindow->consumeMotionMove();
2045 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2046
2047 // Wallpaper closes its channel, but the window remains.
2048 wallpaperWindow->destroyReceiver();
2049 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
2050
2051 // Now the foreground window goes away, but the wallpaper stays, even though its channel
2052 // is no longer valid.
2053 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
2054 foregroundWindow->consumeMotionCancel();
2055}
2056
Arthur Hungc539dbb2022-12-08 07:45:36 +00002057class ShouldSplitTouchFixture : public InputDispatcherTest,
2058 public ::testing::WithParamInterface<bool> {};
2059INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
2060 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002061/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002062 * A single window that receives touch (on top), and a wallpaper window underneath it.
2063 * The top window gets a multitouch gesture.
2064 * Ensure that wallpaper gets the same gesture.
2065 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00002066TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002067 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002068 sp<FakeWindowHandle> foregroundWindow =
2069 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2070 foregroundWindow->setDupTouchToWallpaper(true);
2071 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002072
2073 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002074 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002075 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002076
Arthur Hungc539dbb2022-12-08 07:45:36 +00002077 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002078
2079 // Touch down on top window
2080 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2081 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2082 {100, 100}))
2083 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2084
2085 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00002086 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002087 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2088
2089 // Second finger down on the top window
2090 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002091 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002092 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002093 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2094 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002095 .build();
2096 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2097 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2098 InputEventInjectionSync::WAIT_FOR_RESULT))
2099 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2100
Harry Cutts33476232023-01-30 19:57:29 +00002101 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
2102 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002103 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002104
2105 const MotionEvent secondFingerUpEvent =
2106 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2107 .displayId(ADISPLAY_ID_DEFAULT)
2108 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002109 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2110 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002111 .build();
2112 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2113 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
2114 InputEventInjectionSync::WAIT_FOR_RESULT))
2115 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2116 foregroundWindow->consumeMotionPointerUp(0);
2117 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2118
2119 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002120 injectMotionEvent(mDispatcher,
2121 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2122 AINPUT_SOURCE_TOUCHSCREEN)
2123 .displayId(ADISPLAY_ID_DEFAULT)
2124 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
2125 .pointer(PointerBuilder(/* id */ 1,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002126 ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002127 .x(100)
2128 .y(100))
2129 .build(),
2130 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002131 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2132 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2133 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002134}
2135
2136/**
2137 * Two windows: a window on the left and window on the right.
2138 * A third window, wallpaper, is behind both windows, and spans both top windows.
2139 * The first touch down goes to the left window. A second pointer touches down on the right window.
2140 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2141 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2142 * ACTION_POINTER_DOWN(1).
2143 */
2144TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2145 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2146 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002147 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002148 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002149 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002150
2151 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002152 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002153 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002154 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002155
2156 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002157 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002158 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002159 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002160
2161 mDispatcher->setInputWindows(
2162 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
2163
2164 // Touch down on left window
2165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2166 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2167 {100, 100}))
2168 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2169
2170 // Both foreground window and its wallpaper should receive the touch down
2171 leftWindow->consumeMotionDown();
2172 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2173
2174 // Second finger down on the right window
2175 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002176 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002177 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002178 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2179 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002180 .build();
2181 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2182 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2183 InputEventInjectionSync::WAIT_FOR_RESULT))
2184 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2185
2186 leftWindow->consumeMotionMove();
2187 // Since the touch is split, right window gets ACTION_DOWN
2188 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002189 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002190 expectedWallpaperFlags);
2191
2192 // Now, leftWindow, which received the first finger, disappears.
2193 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
2194 leftWindow->consumeMotionCancel();
2195 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2196 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2197
2198 // The pointer that's still down on the right window moves, and goes to the right window only.
2199 // As far as the dispatcher's concerned though, both pointers are still present.
2200 const MotionEvent secondFingerMoveEvent =
2201 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2202 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002203 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2204 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002205 .build();
2206 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2207 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2208 InputEventInjectionSync::WAIT_FOR_RESULT));
2209 rightWindow->consumeMotionMove();
2210
2211 leftWindow->assertNoEvents();
2212 rightWindow->assertNoEvents();
2213 wallpaperWindow->assertNoEvents();
2214}
2215
Arthur Hungc539dbb2022-12-08 07:45:36 +00002216/**
2217 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2218 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2219 * The right window should receive ACTION_DOWN.
2220 */
2221TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002222 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002223 sp<FakeWindowHandle> leftWindow =
2224 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2225 leftWindow->setFrame(Rect(0, 0, 200, 200));
2226 leftWindow->setDupTouchToWallpaper(true);
2227 leftWindow->setSlippery(true);
2228
2229 sp<FakeWindowHandle> rightWindow =
2230 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2231 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002232
2233 sp<FakeWindowHandle> wallpaperWindow =
2234 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2235 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002236
Arthur Hungc539dbb2022-12-08 07:45:36 +00002237 mDispatcher->setInputWindows(
2238 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002239
Arthur Hungc539dbb2022-12-08 07:45:36 +00002240 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002241 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2242 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002243 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002244 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002245
2246 // Both foreground window and its wallpaper should receive the touch down
2247 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002248 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2249
Arthur Hungc539dbb2022-12-08 07:45:36 +00002250 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002251 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002252 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2253 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002254 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2255
Arthur Hungc539dbb2022-12-08 07:45:36 +00002256 leftWindow->consumeMotionCancel();
2257 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2258 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002259}
2260
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002261/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002262 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2263 * interactive, it might stop sending this flag.
2264 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2265 * to have a consistent input stream.
2266 *
2267 * Test procedure:
2268 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2269 * DOWN (new gesture).
2270 *
2271 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2272 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2273 *
2274 * We technically just need a single window here, but we are using two windows (spy on top and a
2275 * regular window below) to emulate the actual situation where it happens on the device.
2276 */
2277TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2278 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2279 sp<FakeWindowHandle> spyWindow =
2280 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2281 spyWindow->setFrame(Rect(0, 0, 200, 200));
2282 spyWindow->setTrustedOverlay(true);
2283 spyWindow->setSpy(true);
2284
2285 sp<FakeWindowHandle> window =
2286 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2287 window->setFrame(Rect(0, 0, 200, 200));
2288
2289 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2290 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002291
2292 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002293 mDispatcher->notifyMotion(
2294 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2295 .deviceId(touchDeviceId)
2296 .policyFlags(DEFAULT_POLICY_FLAGS)
2297 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2298 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002299
Prabir Pradhan678438e2023-04-13 19:32:51 +00002300 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2301 .deviceId(touchDeviceId)
2302 .policyFlags(DEFAULT_POLICY_FLAGS)
2303 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2304 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2305 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002306 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2307 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2308 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2309 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2310
2311 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002312 mDispatcher->notifyMotion(
2313 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2314 .deviceId(touchDeviceId)
2315 .policyFlags(0)
2316 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2317 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2318 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002319 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2320 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2321
2322 // We don't need to reset the device to reproduce the issue, but the reset event typically
2323 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002324 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002325
2326 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002327 mDispatcher->notifyMotion(
2328 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2329 .deviceId(touchDeviceId)
2330 .policyFlags(DEFAULT_POLICY_FLAGS)
2331 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2332 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002333 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2334 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2335
2336 // No more events
2337 spyWindow->assertNoEvents();
2338 window->assertNoEvents();
2339}
2340
2341/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002342 * Two windows: a window on the left and a window on the right.
2343 * Mouse is hovered from the right window into the left window.
2344 * Next, we tap on the left window, where the cursor was last seen.
2345 * The second tap is done onto the right window.
2346 * The mouse and tap are from two different devices.
2347 * We technically don't need to set the downtime / eventtime for these events, but setting these
2348 * explicitly helps during debugging.
2349 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2350 * In the buggy implementation, a tap on the right window would cause a crash.
2351 */
2352TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2353 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2354 sp<FakeWindowHandle> leftWindow =
2355 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2356 leftWindow->setFrame(Rect(0, 0, 200, 200));
2357
2358 sp<FakeWindowHandle> rightWindow =
2359 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2360 rightWindow->setFrame(Rect(200, 0, 400, 200));
2361
2362 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2363 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2364 // stale.
2365 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2366 const int32_t mouseDeviceId = 6;
2367 const int32_t touchDeviceId = 4;
2368 // Move the cursor from right
2369 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2370 injectMotionEvent(mDispatcher,
2371 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2372 AINPUT_SOURCE_MOUSE)
2373 .deviceId(mouseDeviceId)
2374 .downTime(baseTime + 10)
2375 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002376 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002377 .x(300)
2378 .y(100))
2379 .build()));
2380 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2381
2382 // .. to the left window
2383 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2384 injectMotionEvent(mDispatcher,
2385 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2386 AINPUT_SOURCE_MOUSE)
2387 .deviceId(mouseDeviceId)
2388 .downTime(baseTime + 10)
2389 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002390 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002391 .x(110)
2392 .y(100))
2393 .build()));
2394 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2395 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2396 // Now tap the left window
2397 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2398 injectMotionEvent(mDispatcher,
2399 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2400 AINPUT_SOURCE_TOUCHSCREEN)
2401 .deviceId(touchDeviceId)
2402 .downTime(baseTime + 40)
2403 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002404 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002405 .x(100)
2406 .y(100))
2407 .build()));
2408 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2409 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2410
2411 // release tap
2412 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2413 injectMotionEvent(mDispatcher,
2414 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2415 AINPUT_SOURCE_TOUCHSCREEN)
2416 .deviceId(touchDeviceId)
2417 .downTime(baseTime + 40)
2418 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002419 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002420 .x(100)
2421 .y(100))
2422 .build()));
2423 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2424
2425 // Tap the window on the right
2426 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2427 injectMotionEvent(mDispatcher,
2428 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2429 AINPUT_SOURCE_TOUCHSCREEN)
2430 .deviceId(touchDeviceId)
2431 .downTime(baseTime + 60)
2432 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002433 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002434 .x(300)
2435 .y(100))
2436 .build()));
2437 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2438
2439 // release tap
2440 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2441 injectMotionEvent(mDispatcher,
2442 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2443 AINPUT_SOURCE_TOUCHSCREEN)
2444 .deviceId(touchDeviceId)
2445 .downTime(baseTime + 60)
2446 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002447 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002448 .x(300)
2449 .y(100))
2450 .build()));
2451 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2452
2453 // No more events
2454 leftWindow->assertNoEvents();
2455 rightWindow->assertNoEvents();
2456}
2457
2458/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002459 * Start hovering in a window. While this hover is still active, make another window appear on top.
2460 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2461 * While the top window is present, the hovering is stopped.
2462 * Later, hovering gets resumed again.
2463 * Ensure that new hover gesture is handled correctly.
2464 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2465 * to the window that's currently being hovered over.
2466 */
2467TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2468 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2469 sp<FakeWindowHandle> window =
2470 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2471 window->setFrame(Rect(0, 0, 200, 200));
2472
2473 // Only a single window is present at first
2474 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2475
2476 // Start hovering in the window
2477 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2478 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2479 .build());
2480 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2481
2482 // Now, an obscuring window appears!
2483 sp<FakeWindowHandle> obscuringWindow =
2484 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2485 ADISPLAY_ID_DEFAULT,
2486 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2487 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2488 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2489 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2490 obscuringWindow->setNoInputChannel(true);
2491 obscuringWindow->setFocusable(false);
2492 obscuringWindow->setAlpha(1.0);
2493 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2494
2495 // While this new obscuring window is present, the hovering is stopped
2496 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2497 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2498 .build());
2499 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2500
2501 // Now the obscuring window goes away.
2502 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2503
2504 // And a new hover gesture starts.
2505 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2506 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2507 .build());
2508 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2509}
2510
2511/**
2512 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2513 * the obscuring window.
2514 */
2515TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2516 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2517 sp<FakeWindowHandle> window =
2518 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2519 window->setFrame(Rect(0, 0, 200, 200));
2520
2521 // Only a single window is present at first
2522 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2523
2524 // Start hovering in the window
2525 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2526 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2527 .build());
2528 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2529
2530 // Now, an obscuring window appears!
2531 sp<FakeWindowHandle> obscuringWindow =
2532 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2533 ADISPLAY_ID_DEFAULT,
2534 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2535 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2536 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2537 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2538 obscuringWindow->setNoInputChannel(true);
2539 obscuringWindow->setFocusable(false);
2540 obscuringWindow->setAlpha(1.0);
2541 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2542
2543 // While this new obscuring window is present, the hovering continues. The event can't go to the
2544 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2545 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2546 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2547 .build());
2548 obscuringWindow->assertNoEvents();
2549 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2550
2551 // Now the obscuring window goes away.
2552 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2553
2554 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2555 // so it should generate a HOVER_ENTER
2556 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2557 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2558 .build());
2559 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2560
2561 // Now the MOVE should be getting dispatched normally
2562 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2563 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2564 .build());
2565 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2566}
2567
2568/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002569 * Two windows: a window on the left and a window on the right.
2570 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2571 * down. Then, on the left window, also place second touch pointer down.
2572 * This test tries to reproduce a crash.
2573 * In the buggy implementation, second pointer down on the left window would cause a crash.
2574 */
2575TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2576 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2577 sp<FakeWindowHandle> leftWindow =
2578 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2579 leftWindow->setFrame(Rect(0, 0, 200, 200));
2580
2581 sp<FakeWindowHandle> rightWindow =
2582 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2583 rightWindow->setFrame(Rect(200, 0, 400, 200));
2584
2585 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2586
2587 const int32_t touchDeviceId = 4;
2588 const int32_t mouseDeviceId = 6;
2589 NotifyMotionArgs args;
2590
2591 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002592 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2593 .deviceId(mouseDeviceId)
2594 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2595 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002596 leftWindow->consumeMotionEvent(
2597 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2598
2599 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002600 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2601 .deviceId(mouseDeviceId)
2602 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2603 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2604 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002605
2606 leftWindow->consumeMotionEvent(
2607 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2608 leftWindow->consumeMotionEvent(
2609 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2610
Prabir Pradhan678438e2023-04-13 19:32:51 +00002611 mDispatcher->notifyMotion(
2612 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2613 .deviceId(mouseDeviceId)
2614 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2615 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2616 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2617 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002618 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2619
2620 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002621 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2622 .deviceId(touchDeviceId)
2623 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2624 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002625 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2626
2627 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2628
2629 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002630 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2631 .deviceId(touchDeviceId)
2632 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2633 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2634 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002635 leftWindow->consumeMotionEvent(
2636 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2637 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2638 // current implementation.
2639 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2640 rightWindow->consumeMotionEvent(
2641 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2642
2643 leftWindow->assertNoEvents();
2644 rightWindow->assertNoEvents();
2645}
2646
2647/**
2648 * On a single window, use two different devices: mouse and touch.
2649 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2650 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2651 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2652 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2653 * represent a new gesture.
2654 */
2655TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2656 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2657 sp<FakeWindowHandle> window =
2658 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2659 window->setFrame(Rect(0, 0, 400, 400));
2660
2661 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2662
2663 const int32_t touchDeviceId = 4;
2664 const int32_t mouseDeviceId = 6;
2665 NotifyMotionArgs args;
2666
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002667 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002668 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2669 .deviceId(touchDeviceId)
2670 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2671 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002672 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002673 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2674 .deviceId(touchDeviceId)
2675 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2676 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2677 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002678 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002679 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2680 .deviceId(touchDeviceId)
2681 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2682 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2683 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002684 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2685 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2686 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2687
2688 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002689 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2690 .deviceId(mouseDeviceId)
2691 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2692 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2693 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002694
2695 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002696 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002697 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2698
Prabir Pradhan678438e2023-04-13 19:32:51 +00002699 mDispatcher->notifyMotion(
2700 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2701 .deviceId(mouseDeviceId)
2702 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2703 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2704 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2705 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002706 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2707
2708 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002709 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2710 .deviceId(touchDeviceId)
2711 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2712 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2713 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002714 // The pointer_down event should be ignored
2715 window->assertNoEvents();
2716}
2717
2718/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002719 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2720 * the injected event.
2721 */
2722TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2723 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2724 sp<FakeWindowHandle> window =
2725 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2726 window->setFrame(Rect(0, 0, 400, 400));
2727
2728 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2729
2730 const int32_t touchDeviceId = 4;
2731 NotifyMotionArgs args;
2732 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2733 // completion.
2734 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2735 injectMotionEvent(mDispatcher,
2736 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2737 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002738 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002739 .x(50)
2740 .y(50))
2741 .build()));
2742 window->consumeMotionEvent(
2743 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2744
2745 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2746 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002747 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2748 .deviceId(touchDeviceId)
2749 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2750 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002751
2752 window->consumeMotionEvent(
2753 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2754 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2755}
2756
2757/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002758 * This test is similar to the test above, but the sequence of injected events is different.
2759 *
2760 * Two windows: a window on the left and a window on the right.
2761 * Mouse is hovered over the left window.
2762 * Next, we tap on the left window, where the cursor was last seen.
2763 *
2764 * After that, we inject one finger down onto the right window, and then a second finger down onto
2765 * the left window.
2766 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2767 * window (first), and then another on the left window (second).
2768 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2769 * In the buggy implementation, second finger down on the left window would cause a crash.
2770 */
2771TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2772 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2773 sp<FakeWindowHandle> leftWindow =
2774 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2775 leftWindow->setFrame(Rect(0, 0, 200, 200));
2776
2777 sp<FakeWindowHandle> rightWindow =
2778 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2779 rightWindow->setFrame(Rect(200, 0, 400, 200));
2780
2781 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2782
2783 const int32_t mouseDeviceId = 6;
2784 const int32_t touchDeviceId = 4;
2785 // Hover over the left window. Keep the cursor there.
2786 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2787 injectMotionEvent(mDispatcher,
2788 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2789 AINPUT_SOURCE_MOUSE)
2790 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002791 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002792 .x(50)
2793 .y(50))
2794 .build()));
2795 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2796
2797 // Tap on left window
2798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2799 injectMotionEvent(mDispatcher,
2800 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2801 AINPUT_SOURCE_TOUCHSCREEN)
2802 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002803 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002804 .x(100)
2805 .y(100))
2806 .build()));
2807
2808 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2809 injectMotionEvent(mDispatcher,
2810 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2811 AINPUT_SOURCE_TOUCHSCREEN)
2812 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002813 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002814 .x(100)
2815 .y(100))
2816 .build()));
2817 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2818 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2819 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2820
2821 // First finger down on right window
2822 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2823 injectMotionEvent(mDispatcher,
2824 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2825 AINPUT_SOURCE_TOUCHSCREEN)
2826 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002827 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002828 .x(300)
2829 .y(100))
2830 .build()));
2831 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2832
2833 // Second finger down on the left window
2834 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2835 injectMotionEvent(mDispatcher,
2836 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2837 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002838 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002839 .x(300)
2840 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002841 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002842 .x(100)
2843 .y(100))
2844 .build()));
2845 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2846 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2847
2848 // No more events
2849 leftWindow->assertNoEvents();
2850 rightWindow->assertNoEvents();
2851}
2852
2853/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002854 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2855 * While the touch is down, new hover events from the stylus device should be ignored. After the
2856 * touch is gone, stylus hovering should start working again.
2857 */
2858TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2859 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2860 sp<FakeWindowHandle> window =
2861 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2862 window->setFrame(Rect(0, 0, 200, 200));
2863
2864 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2865
2866 const int32_t stylusDeviceId = 5;
2867 const int32_t touchDeviceId = 4;
2868 // Start hovering with stylus
2869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2870 injectMotionEvent(mDispatcher,
2871 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2872 AINPUT_SOURCE_STYLUS)
2873 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002874 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002875 .x(50)
2876 .y(50))
2877 .build()));
2878 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2879
2880 // Finger down on the window
2881 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2882 injectMotionEvent(mDispatcher,
2883 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2884 AINPUT_SOURCE_TOUCHSCREEN)
2885 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002886 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002887 .x(100)
2888 .y(100))
2889 .build()));
2890 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2891 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2892
2893 // Try to continue hovering with stylus. Since we are already down, injection should fail
2894 ASSERT_EQ(InputEventInjectionResult::FAILED,
2895 injectMotionEvent(mDispatcher,
2896 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2897 AINPUT_SOURCE_STYLUS)
2898 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002899 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002900 .x(50)
2901 .y(50))
2902 .build()));
2903 // No event should be sent. This event should be ignored because a pointer from another device
2904 // is already down.
2905
2906 // Lift up the finger
2907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2908 injectMotionEvent(mDispatcher,
2909 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2910 AINPUT_SOURCE_TOUCHSCREEN)
2911 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002912 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002913 .x(100)
2914 .y(100))
2915 .build()));
2916 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2917
2918 // Now that the touch is gone, stylus hovering should start working again
2919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2920 injectMotionEvent(mDispatcher,
2921 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2922 AINPUT_SOURCE_STYLUS)
2923 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002924 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002925 .x(50)
2926 .y(50))
2927 .build()));
2928 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2929 // No more events
2930 window->assertNoEvents();
2931}
2932
2933/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002934 * A spy window above a window with no input channel.
2935 * Start hovering with a stylus device, and then tap with it.
2936 * Ensure spy window receives the entire sequence.
2937 */
2938TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2939 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2940 sp<FakeWindowHandle> spyWindow =
2941 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2942 spyWindow->setFrame(Rect(0, 0, 200, 200));
2943 spyWindow->setTrustedOverlay(true);
2944 spyWindow->setSpy(true);
2945 sp<FakeWindowHandle> window =
2946 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2947 window->setNoInputChannel(true);
2948 window->setFrame(Rect(0, 0, 200, 200));
2949
2950 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2951
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002952 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002953 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2954 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2955 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002956 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2957 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002958 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2959 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2960 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002961 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2962
2963 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002964 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2965 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2966 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002967 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2968
2969 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002970 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2971 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2972 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002973 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2974
2975 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002976 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2977 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2978 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002979 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2980 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002981 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2982 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2983 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002984 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2985
2986 // No more events
2987 spyWindow->assertNoEvents();
2988 window->assertNoEvents();
2989}
2990
2991/**
2992 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2993 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2994 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2995 * While the mouse is down, new move events from the touch device should be ignored.
2996 */
2997TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2998 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2999 sp<FakeWindowHandle> spyWindow =
3000 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3001 spyWindow->setFrame(Rect(0, 0, 200, 200));
3002 spyWindow->setTrustedOverlay(true);
3003 spyWindow->setSpy(true);
3004 sp<FakeWindowHandle> window =
3005 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3006 window->setFrame(Rect(0, 0, 200, 200));
3007
3008 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3009
3010 const int32_t mouseDeviceId = 7;
3011 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003012
3013 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003014 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3015 .deviceId(mouseDeviceId)
3016 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3017 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003018 spyWindow->consumeMotionEvent(
3019 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3020 window->consumeMotionEvent(
3021 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3022
3023 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003024 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3025 .deviceId(touchDeviceId)
3026 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3027 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003028 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3029 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3030 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3031 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3032
Prabir Pradhan678438e2023-04-13 19:32:51 +00003033 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3034 .deviceId(touchDeviceId)
3035 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3036 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003037 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3038 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3039
3040 // Pilfer the stream
3041 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3042 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3043
Prabir Pradhan678438e2023-04-13 19:32:51 +00003044 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3045 .deviceId(touchDeviceId)
3046 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3047 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003048 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3049
3050 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003051 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3052 .deviceId(mouseDeviceId)
3053 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3054 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3055 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003056
3057 spyWindow->consumeMotionEvent(
3058 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3059 spyWindow->consumeMotionEvent(
3060 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3061 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3062
Prabir Pradhan678438e2023-04-13 19:32:51 +00003063 mDispatcher->notifyMotion(
3064 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3065 .deviceId(mouseDeviceId)
3066 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3067 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3068 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3069 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003070 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3071 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3072
3073 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003074 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3075 .deviceId(mouseDeviceId)
3076 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3077 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3078 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003079 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3080 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3081
3082 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003083 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3084 .deviceId(touchDeviceId)
3085 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3086 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003087
3088 // No more events
3089 spyWindow->assertNoEvents();
3090 window->assertNoEvents();
3091}
3092
3093/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003094 * On the display, have a single window, and also an area where there's no window.
3095 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3096 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3097 */
3098TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3099 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3100 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003101 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003102
3103 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003104
3105 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003106 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003107
3108 mDispatcher->waitForIdle();
3109 window->assertNoEvents();
3110
3111 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003112 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003113 mDispatcher->waitForIdle();
3114 window->consumeMotionDown();
3115}
3116
3117/**
3118 * Same test as above, but instead of touching the empty space, the first touch goes to
3119 * non-touchable window.
3120 */
3121TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3122 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3123 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003124 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003125 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3126 window1->setTouchable(false);
3127 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003128 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003129 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3130
3131 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
3132
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003133 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003134 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003135
3136 mDispatcher->waitForIdle();
3137 window1->assertNoEvents();
3138 window2->assertNoEvents();
3139
3140 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003141 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003142 mDispatcher->waitForIdle();
3143 window2->consumeMotionDown();
3144}
3145
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003146/**
3147 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3148 * to the event time of the first ACTION_DOWN sent to the particular window.
3149 */
3150TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3151 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3152 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003153 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003154 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3155 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003156 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003157 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3158
3159 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
3160
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003161 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003162 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003163
3164 mDispatcher->waitForIdle();
3165 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003166 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003167 window2->assertNoEvents();
3168 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
3169 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
3170 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
3171
3172 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003173 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003174 mDispatcher->waitForIdle();
3175 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003176 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003177 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
3178 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
3179 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
3180 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
3181
3182 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003183 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003184 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003185 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003186
3187 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003188 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003189 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003190 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003191
3192 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3193 window1->consumeMotionMove();
3194 window1->assertNoEvents();
3195
3196 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003197 mDispatcher->notifyMotion(
3198 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003199 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003200 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003201
Prabir Pradhan678438e2023-04-13 19:32:51 +00003202 mDispatcher->notifyMotion(
3203 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003204 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003205 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003206}
3207
Garfield Tandf26e862020-07-01 20:18:19 -07003208TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003209 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003210 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003211 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003212 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003213 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003214 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003215 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003216
3217 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3218
3219 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3220
3221 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003223 injectMotionEvent(mDispatcher,
3224 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3225 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003226 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003227 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003228 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003229
3230 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003231 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003232 injectMotionEvent(mDispatcher,
3233 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3234 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003235 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003236 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003237 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3238 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003239
3240 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003241 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003242 injectMotionEvent(mDispatcher,
3243 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3244 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003245 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003246 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003247 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3248 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003249
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003251 injectMotionEvent(mDispatcher,
3252 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3253 AINPUT_SOURCE_MOUSE)
3254 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3255 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003256 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003257 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003258 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003259
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003261 injectMotionEvent(mDispatcher,
3262 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3263 AINPUT_SOURCE_MOUSE)
3264 .buttonState(0)
3265 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003266 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003267 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003268 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003269
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003271 injectMotionEvent(mDispatcher,
3272 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3273 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003274 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003275 .build()));
3276 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3277
3278 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003279 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003280 injectMotionEvent(mDispatcher,
3281 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3282 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003283 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003284 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003285 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003286
3287 // No more events
3288 windowLeft->assertNoEvents();
3289 windowRight->assertNoEvents();
3290}
3291
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003292/**
3293 * Put two fingers down (and don't release them) and click the mouse button.
3294 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3295 * currently active gesture should be canceled, and the new one should proceed.
3296 */
3297TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3298 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3299 sp<FakeWindowHandle> window =
3300 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3301 window->setFrame(Rect(0, 0, 600, 800));
3302
3303 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3304
3305 const int32_t touchDeviceId = 4;
3306 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003307
3308 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003309 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3310 .deviceId(touchDeviceId)
3311 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3312 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003313
Prabir Pradhan678438e2023-04-13 19:32:51 +00003314 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3315 .deviceId(touchDeviceId)
3316 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3317 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3318 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003319 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3320 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3321
3322 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003323 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3324 .deviceId(mouseDeviceId)
3325 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3326 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3327 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003328 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3329 WithPointerCount(2u)));
3330 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3331
Prabir Pradhan678438e2023-04-13 19:32:51 +00003332 mDispatcher->notifyMotion(
3333 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3334 .deviceId(mouseDeviceId)
3335 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3336 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3337 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3338 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003339 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3340
3341 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3342 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003343 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3344 .deviceId(touchDeviceId)
3345 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3346 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3347 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003348 window->assertNoEvents();
3349}
3350
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003351TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3352 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3353
3354 sp<FakeWindowHandle> spyWindow =
3355 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3356 spyWindow->setFrame(Rect(0, 0, 600, 800));
3357 spyWindow->setTrustedOverlay(true);
3358 spyWindow->setSpy(true);
3359 sp<FakeWindowHandle> window =
3360 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3361 window->setFrame(Rect(0, 0, 600, 800));
3362
3363 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3364 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3365
3366 // Send mouse cursor to the window
3367 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3368 injectMotionEvent(mDispatcher,
3369 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3370 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003371 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003372 .x(100)
3373 .y(100))
3374 .build()));
3375
3376 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3377 WithSource(AINPUT_SOURCE_MOUSE)));
3378 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3379 WithSource(AINPUT_SOURCE_MOUSE)));
3380
3381 window->assertNoEvents();
3382 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003383}
3384
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003385TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3386 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3387
3388 sp<FakeWindowHandle> spyWindow =
3389 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3390 spyWindow->setFrame(Rect(0, 0, 600, 800));
3391 spyWindow->setTrustedOverlay(true);
3392 spyWindow->setSpy(true);
3393 sp<FakeWindowHandle> window =
3394 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3395 window->setFrame(Rect(0, 0, 600, 800));
3396
3397 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3398 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3399
3400 // Send mouse cursor to the window
3401 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3402 injectMotionEvent(mDispatcher,
3403 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3404 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003405 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003406 .x(100)
3407 .y(100))
3408 .build()));
3409
3410 // Move mouse cursor
3411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3412 injectMotionEvent(mDispatcher,
3413 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3414 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003415 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003416 .x(110)
3417 .y(110))
3418 .build()));
3419
3420 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3421 WithSource(AINPUT_SOURCE_MOUSE)));
3422 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3423 WithSource(AINPUT_SOURCE_MOUSE)));
3424 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3425 WithSource(AINPUT_SOURCE_MOUSE)));
3426 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3427 WithSource(AINPUT_SOURCE_MOUSE)));
3428 // Touch down on the window
3429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3430 injectMotionEvent(mDispatcher,
3431 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3432 AINPUT_SOURCE_TOUCHSCREEN)
3433 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003434 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003435 .x(200)
3436 .y(200))
3437 .build()));
3438 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3439 WithSource(AINPUT_SOURCE_MOUSE)));
3440 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3441 WithSource(AINPUT_SOURCE_MOUSE)));
3442 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3443 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3444 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3445 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3446
3447 // pilfer the motion, retaining the gesture on the spy window.
3448 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3449 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3450 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3451
3452 // Touch UP on the window
3453 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3454 injectMotionEvent(mDispatcher,
3455 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3456 AINPUT_SOURCE_TOUCHSCREEN)
3457 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003458 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003459 .x(200)
3460 .y(200))
3461 .build()));
3462 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3463 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3464
3465 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3466 // to send a new gesture. It should again go to both windows (spy and the window below), just
3467 // like the first gesture did, before pilfering. The window configuration has not changed.
3468
3469 // One more tap - DOWN
3470 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3471 injectMotionEvent(mDispatcher,
3472 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3473 AINPUT_SOURCE_TOUCHSCREEN)
3474 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003475 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003476 .x(250)
3477 .y(250))
3478 .build()));
3479 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3480 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3481 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3482 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3483
3484 // Touch UP on the window
3485 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3486 injectMotionEvent(mDispatcher,
3487 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3488 AINPUT_SOURCE_TOUCHSCREEN)
3489 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003490 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003491 .x(250)
3492 .y(250))
3493 .build()));
3494 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3495 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3496 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3497 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3498
3499 window->assertNoEvents();
3500 spyWindow->assertNoEvents();
3501}
3502
Garfield Tandf26e862020-07-01 20:18:19 -07003503// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3504// directly in this test.
3505TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003506 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003507 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003508 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003509 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003510
3511 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3512
3513 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3514
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003515 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003516 injectMotionEvent(mDispatcher,
3517 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3518 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003519 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003520 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003521 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003522 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003523 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003524 injectMotionEvent(mDispatcher,
3525 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3526 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003527 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003528 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003529 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3530 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003531
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003533 injectMotionEvent(mDispatcher,
3534 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3535 AINPUT_SOURCE_MOUSE)
3536 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3537 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003538 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003539 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003540 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003541
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003542 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003543 injectMotionEvent(mDispatcher,
3544 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3545 AINPUT_SOURCE_MOUSE)
3546 .buttonState(0)
3547 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003548 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003549 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003550 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003551
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003553 injectMotionEvent(mDispatcher,
3554 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3555 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003556 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003557 .build()));
3558 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3559
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003560 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3561 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3562 ASSERT_EQ(InputEventInjectionResult::FAILED,
Garfield Tandf26e862020-07-01 20:18:19 -07003563 injectMotionEvent(mDispatcher,
3564 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3565 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003566 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003567 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003568 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003569}
3570
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003571/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003572 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3573 * is generated.
3574 */
3575TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3576 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3577 sp<FakeWindowHandle> window =
3578 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3579 window->setFrame(Rect(0, 0, 1200, 800));
3580
3581 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3582
3583 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3584
3585 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3586 injectMotionEvent(mDispatcher,
3587 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3588 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003589 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003590 .x(300)
3591 .y(400))
3592 .build()));
3593 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3594
3595 // Remove the window, but keep the channel.
3596 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3597 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3598}
3599
3600/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003601 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3602 */
3603TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3604 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3605 sp<FakeWindowHandle> window =
3606 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3607 window->setFrame(Rect(0, 0, 100, 100));
3608
3609 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3610
3611 const int32_t mouseDeviceId = 7;
3612 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003613
3614 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003615 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3616 .deviceId(mouseDeviceId)
3617 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3618 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003619 window->consumeMotionEvent(
3620 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3621
3622 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003623 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3624 .deviceId(touchDeviceId)
3625 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3626 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003627
3628 window->consumeMotionEvent(
3629 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3630 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3631}
3632
3633/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003634 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003635 * The tap causes a HOVER_EXIT event to be generated because the current event
3636 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003637 */
3638TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3639 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3640 sp<FakeWindowHandle> window =
3641 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3642 window->setFrame(Rect(0, 0, 100, 100));
3643
3644 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3645
3646 // Inject a hover_move from mouse.
3647 NotifyMotionArgs motionArgs =
3648 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3649 ADISPLAY_ID_DEFAULT, {{50, 50}});
3650 motionArgs.xCursorPosition = 50;
3651 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003652 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003653 ASSERT_NO_FATAL_FAILURE(
3654 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3655 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003656
3657 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003658 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3659 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3660 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003661 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003662 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3663 WithSource(AINPUT_SOURCE_MOUSE))));
3664
3665 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003666 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3667 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3668
Prabir Pradhan678438e2023-04-13 19:32:51 +00003669 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3670 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003671 ASSERT_NO_FATAL_FAILURE(
3672 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3673 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3674}
3675
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003676TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3677 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3678 sp<FakeWindowHandle> windowDefaultDisplay =
3679 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3680 ADISPLAY_ID_DEFAULT);
3681 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3682 sp<FakeWindowHandle> windowSecondDisplay =
3683 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3684 SECOND_DISPLAY_ID);
3685 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3686
3687 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3688 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3689
3690 // Set cursor position in window in default display and check that hover enter and move
3691 // events are generated.
3692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3693 injectMotionEvent(mDispatcher,
3694 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3695 AINPUT_SOURCE_MOUSE)
3696 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003697 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003698 .x(300)
3699 .y(600))
3700 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003701 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003702
3703 // Remove all windows in secondary display and check that no event happens on window in
3704 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003705 mDispatcher->setInputWindows(
3706 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003707 windowDefaultDisplay->assertNoEvents();
3708
3709 // Move cursor position in window in default display and check that only hover move
3710 // event is generated and not hover enter event.
3711 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3712 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3713 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3714 injectMotionEvent(mDispatcher,
3715 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3716 AINPUT_SOURCE_MOUSE)
3717 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003718 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003719 .x(400)
3720 .y(700))
3721 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003722 windowDefaultDisplay->consumeMotionEvent(
3723 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3724 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003725 windowDefaultDisplay->assertNoEvents();
3726}
3727
Garfield Tan00f511d2019-06-12 16:55:40 -07003728TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003729 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003730
3731 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003732 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003733 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003734 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003735 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003736 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003737
3738 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3739
Arthur Hung72d8dc32020-03-28 00:48:39 +00003740 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003741
3742 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3743 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003745 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003746 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003747 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003748 windowRight->assertNoEvents();
3749}
3750
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003751TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003752 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003753 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3754 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003755 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003756
Arthur Hung72d8dc32020-03-28 00:48:39 +00003757 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003758 setFocusedWindow(window);
3759
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003760 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003761
Prabir Pradhan678438e2023-04-13 19:32:51 +00003762 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003763
3764 // Window should receive key down event.
3765 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3766
3767 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3768 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003769 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003770 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003771 AKEY_EVENT_FLAG_CANCELED);
3772}
3773
3774TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003775 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003776 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3777 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003778
Arthur Hung72d8dc32020-03-28 00:48:39 +00003779 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003780
Prabir Pradhan678438e2023-04-13 19:32:51 +00003781 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3782 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003783
3784 // Window should receive motion down event.
3785 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3786
3787 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3788 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003789 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003790 window->consumeMotionEvent(
3791 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003792}
3793
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003794TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3796 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3797 "Fake Window", ADISPLAY_ID_DEFAULT);
3798
3799 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3800
3801 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3802 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3803 .build());
3804
3805 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3806
3807 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3808 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3809 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3810
3811 // After the device has been reset, a new hovering stream can be sent to the window
3812 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3813 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3814 .build());
3815 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3816}
3817
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003818TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3819 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003820 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3821 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003822 window->setFocusable(true);
3823
3824 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3825 setFocusedWindow(window);
3826
3827 window->consumeFocusEvent(true);
3828
Prabir Pradhan678438e2023-04-13 19:32:51 +00003829 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003830 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3831 const nsecs_t injectTime = keyArgs.eventTime;
3832 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003833 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003834 // The dispatching time should be always greater than or equal to intercept key timeout.
3835 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3836 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3837 std::chrono::nanoseconds(interceptKeyTimeout).count());
3838}
3839
3840TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003842 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3843 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003844 window->setFocusable(true);
3845
3846 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3847 setFocusedWindow(window);
3848
3849 window->consumeFocusEvent(true);
3850
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003851 mFakePolicy->setInterceptKeyTimeout(150ms);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003852 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
3853 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003854
3855 // Window should receive key event immediately when same key up.
3856 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3857 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3858}
3859
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003860/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003861 * Two windows. First is a regular window. Second does not overlap with the first, and has
3862 * WATCH_OUTSIDE_TOUCH.
3863 * Both windows are owned by the same UID.
3864 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3865 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3866 */
3867TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3868 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3869 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3870 "First Window", ADISPLAY_ID_DEFAULT);
3871 window->setFrame(Rect{0, 0, 100, 100});
3872
3873 sp<FakeWindowHandle> outsideWindow =
3874 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3875 ADISPLAY_ID_DEFAULT);
3876 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3877 outsideWindow->setWatchOutsideTouch(true);
3878 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3879 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3880
3881 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003882 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3883 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3884 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003885 window->consumeMotionDown();
3886 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3887 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3888 outsideWindow->consumeMotionEvent(
3889 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3890}
3891
3892/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003893 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3894 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3895 * ACTION_OUTSIDE event is sent per gesture.
3896 */
3897TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3898 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3899 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003900 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3901 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003902 window->setWatchOutsideTouch(true);
3903 window->setFrame(Rect{0, 0, 100, 100});
3904 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003905 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3906 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003907 secondWindow->setFrame(Rect{100, 100, 200, 200});
3908 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003909 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3910 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003911 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3912 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3913
3914 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003915 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3916 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3917 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003918 window->assertNoEvents();
3919 secondWindow->assertNoEvents();
3920
3921 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3922 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003923 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3924 ADISPLAY_ID_DEFAULT,
3925 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003926 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3927 window->consumeMotionEvent(
3928 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003929 secondWindow->consumeMotionDown();
3930 thirdWindow->assertNoEvents();
3931
3932 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3933 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003934 mDispatcher->notifyMotion(
3935 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3936 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003937 window->assertNoEvents();
3938 secondWindow->consumeMotionMove();
3939 thirdWindow->consumeMotionDown();
3940}
3941
Prabir Pradhan814fe082022-07-22 20:22:18 +00003942TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3943 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003944 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3945 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003946 window->setFocusable(true);
3947
3948 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
3949 setFocusedWindow(window);
3950
3951 window->consumeFocusEvent(true);
3952
Prabir Pradhan678438e2023-04-13 19:32:51 +00003953 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3954 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3955 mDispatcher->notifyKey(keyDown);
3956 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003957
3958 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3959 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3960
3961 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
3962 mDispatcher->onWindowInfosChanged({}, {});
3963
3964 window->consumeFocusEvent(false);
3965
Prabir Pradhan678438e2023-04-13 19:32:51 +00003966 mDispatcher->notifyKey(keyDown);
3967 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003968 window->assertNoEvents();
3969}
3970
Arthur Hung96483742022-11-15 03:30:48 +00003971TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3972 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3973 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3974 "Fake Window", ADISPLAY_ID_DEFAULT);
3975 // Ensure window is non-split and have some transform.
3976 window->setPreventSplitting(true);
3977 window->setWindowOffset(20, 40);
3978 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
3979
3980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3981 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3982 {50, 50}))
3983 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3984 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3985
3986 const MotionEvent secondFingerDownEvent =
3987 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3988 .displayId(ADISPLAY_ID_DEFAULT)
3989 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003990 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3991 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003992 .build();
3993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3994 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3995 InputEventInjectionSync::WAIT_FOR_RESULT))
3996 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3997
3998 const MotionEvent* event = window->consumeMotion();
3999 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4000 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4001 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4002 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4003 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4004}
4005
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004006/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004007 * Ensure the correct coordinate spaces are used by InputDispatcher.
4008 *
4009 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4010 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4011 * space.
4012 */
4013class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4014public:
4015 void SetUp() override {
4016 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004017 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004018 }
4019
4020 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4021 gui::DisplayInfo info;
4022 info.displayId = displayId;
4023 info.transform = transform;
4024 mDisplayInfos.push_back(std::move(info));
4025 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
4026 }
4027
4028 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4029 mWindowInfos.push_back(*windowHandle->getInfo());
4030 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
4031 }
4032
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004033 void removeAllWindowsAndDisplays() {
4034 mDisplayInfos.clear();
4035 mWindowInfos.clear();
4036 }
4037
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004038 // Set up a test scenario where the display has a scaled projection and there are two windows
4039 // on the display.
4040 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4041 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4042 // respectively.
4043 ui::Transform displayTransform;
4044 displayTransform.set(2, 0, 0, 4);
4045 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4046
4047 std::shared_ptr<FakeApplicationHandle> application =
4048 std::make_shared<FakeApplicationHandle>();
4049
4050 // Add two windows to the display. Their frames are represented in the display space.
4051 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004052 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4053 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004054 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4055 addWindow(firstWindow);
4056
4057 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004058 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4059 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004060 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4061 addWindow(secondWindow);
4062 return {std::move(firstWindow), std::move(secondWindow)};
4063 }
4064
4065private:
4066 std::vector<gui::DisplayInfo> mDisplayInfos;
4067 std::vector<gui::WindowInfo> mWindowInfos;
4068};
4069
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004070TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004071 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4072 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004073 // selected so that if the hit test was performed with the point and the bounds being in
4074 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004075 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4076 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4077 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004078
4079 firstWindow->consumeMotionDown();
4080 secondWindow->assertNoEvents();
4081}
4082
4083// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4084// the event should be treated as being in the logical display space.
4085TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4086 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4087 // Send down to the first window. The point is represented in the logical display space. The
4088 // point is selected so that if the hit test was done in logical display space, then it would
4089 // end up in the incorrect window.
4090 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4091 PointF{75 * 2, 55 * 4});
4092
4093 firstWindow->consumeMotionDown();
4094 secondWindow->assertNoEvents();
4095}
4096
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004097// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4098// event should be treated as being in the logical display space.
4099TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4100 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4101
4102 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4103 ui::Transform injectedEventTransform;
4104 injectedEventTransform.set(matrix);
4105 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4106 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4107
4108 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4109 .displayId(ADISPLAY_ID_DEFAULT)
4110 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004111 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004112 .x(untransformedPoint.x)
4113 .y(untransformedPoint.y))
4114 .build();
4115 event.transform(matrix);
4116
4117 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
4118 InputEventInjectionSync::WAIT_FOR_RESULT);
4119
4120 firstWindow->consumeMotionDown();
4121 secondWindow->assertNoEvents();
4122}
4123
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004124TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4125 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4126
4127 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004128 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4129 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4130 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004131
4132 firstWindow->assertNoEvents();
4133 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004134 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004135 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4136
4137 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4138 EXPECT_EQ(300, event->getRawX(0));
4139 EXPECT_EQ(880, event->getRawY(0));
4140
4141 // Ensure that the x and y values are in the window's coordinate space.
4142 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4143 // the logical display space. This will be the origin of the window space.
4144 EXPECT_EQ(100, event->getX(0));
4145 EXPECT_EQ(80, event->getY(0));
4146}
4147
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004148/** Ensure consistent behavior of InputDispatcher in all orientations. */
4149class InputDispatcherDisplayOrientationFixture
4150 : public InputDispatcherDisplayProjectionTest,
4151 public ::testing::WithParamInterface<ui::Rotation> {};
4152
4153// This test verifies the touchable region of a window for all rotations of the display by tapping
4154// in different locations on the display, specifically points close to the four corners of a
4155// window.
4156TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4157 constexpr static int32_t displayWidth = 400;
4158 constexpr static int32_t displayHeight = 800;
4159
4160 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4161
4162 const auto rotation = GetParam();
4163
4164 // Set up the display with the specified rotation.
4165 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4166 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4167 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4168 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4169 logicalDisplayWidth, logicalDisplayHeight);
4170 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4171
4172 // Create a window with its bounds determined in the logical display.
4173 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4174 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4175 sp<FakeWindowHandle> window =
4176 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4177 window->setFrame(frameInDisplay, displayTransform);
4178 addWindow(window);
4179
4180 // The following points in logical display space should be inside the window.
4181 static const std::array<vec2, 4> insidePoints{
4182 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4183 for (const auto pointInsideWindow : insidePoints) {
4184 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4185 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004186 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4187 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4188 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004189 window->consumeMotionDown();
4190
Prabir Pradhan678438e2023-04-13 19:32:51 +00004191 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4192 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4193 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004194 window->consumeMotionUp();
4195 }
4196
4197 // The following points in logical display space should be outside the window.
4198 static const std::array<vec2, 5> outsidePoints{
4199 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4200 for (const auto pointOutsideWindow : outsidePoints) {
4201 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4202 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004203 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4204 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4205 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004206
Prabir Pradhan678438e2023-04-13 19:32:51 +00004207 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4208 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4209 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004210 }
4211 window->assertNoEvents();
4212}
4213
4214// Run the precision tests for all rotations.
4215INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4216 InputDispatcherDisplayOrientationFixture,
4217 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4218 ui::ROTATION_270),
4219 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4220 return ftl::enum_string(testParamInfo.param);
4221 });
4222
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004223using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4224 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004225
4226class TransferTouchFixture : public InputDispatcherTest,
4227 public ::testing::WithParamInterface<TransferFunction> {};
4228
4229TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004230 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004231
4232 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004233 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004234 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4235 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004236 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004237 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004238 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4239 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004240 sp<FakeWindowHandle> wallpaper =
4241 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4242 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004243 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004244 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004245
4246 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004247 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4248 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004249
Svet Ganov5d3bc372020-01-26 23:11:07 -08004250 // Only the first window should get the down event
4251 firstWindow->consumeMotionDown();
4252 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004253 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004254
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004255 // Transfer touch to the second window
4256 TransferFunction f = GetParam();
4257 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4258 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004259 // The first window gets cancel and the second gets down
4260 firstWindow->consumeMotionCancel();
4261 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004262 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004263
4264 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004265 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4266 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004267 // The first window gets no events and the second gets up
4268 firstWindow->assertNoEvents();
4269 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004270 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004271}
4272
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004273/**
4274 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4275 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4276 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4277 * natural to the user.
4278 * In this test, we are sending a pointer to both spy window and first window. We then try to
4279 * transfer touch to the second window. The dispatcher should identify the first window as the
4280 * one that should lose the gesture, and therefore the action should be to move the gesture from
4281 * the first window to the second.
4282 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4283 * the other API, as well.
4284 */
4285TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4286 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4287
4288 // Create a couple of windows + a spy window
4289 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004290 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004291 spyWindow->setTrustedOverlay(true);
4292 spyWindow->setSpy(true);
4293 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004294 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004295 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004296 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004297
4298 // Add the windows to the dispatcher
4299 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4300
4301 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004302 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4303 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004304 // Only the first window and spy should get the down event
4305 spyWindow->consumeMotionDown();
4306 firstWindow->consumeMotionDown();
4307
4308 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4309 // if f === 'transferTouch'.
4310 TransferFunction f = GetParam();
4311 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4312 ASSERT_TRUE(success);
4313 // The first window gets cancel and the second gets down
4314 firstWindow->consumeMotionCancel();
4315 secondWindow->consumeMotionDown();
4316
4317 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004318 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4319 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004320 // The first window gets no events and the second+spy get up
4321 firstWindow->assertNoEvents();
4322 spyWindow->consumeMotionUp();
4323 secondWindow->consumeMotionUp();
4324}
4325
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004326TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004327 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004328
4329 PointF touchPoint = {10, 10};
4330
4331 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004332 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004333 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4334 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004335 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004336 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004337 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4338 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004339 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004340
4341 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004342 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004343
4344 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004345 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4346 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4347 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004348 // Only the first window should get the down event
4349 firstWindow->consumeMotionDown();
4350 secondWindow->assertNoEvents();
4351
4352 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004353 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4354 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004355 // Only the first window should get the pointer down event
4356 firstWindow->consumeMotionPointerDown(1);
4357 secondWindow->assertNoEvents();
4358
4359 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004360 TransferFunction f = GetParam();
4361 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4362 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004363 // The first window gets cancel and the second gets down and pointer down
4364 firstWindow->consumeMotionCancel();
4365 secondWindow->consumeMotionDown();
4366 secondWindow->consumeMotionPointerDown(1);
4367
4368 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004369 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4370 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004371 // The first window gets nothing and the second gets pointer up
4372 firstWindow->assertNoEvents();
4373 secondWindow->consumeMotionPointerUp(1);
4374
4375 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004376 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4377 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004378 // The first window gets nothing and the second gets up
4379 firstWindow->assertNoEvents();
4380 secondWindow->consumeMotionUp();
4381}
4382
Arthur Hungc539dbb2022-12-08 07:45:36 +00004383TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4384 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4385
4386 // Create a couple of windows
4387 sp<FakeWindowHandle> firstWindow =
4388 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4389 ADISPLAY_ID_DEFAULT);
4390 firstWindow->setDupTouchToWallpaper(true);
4391 sp<FakeWindowHandle> secondWindow =
4392 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4393 ADISPLAY_ID_DEFAULT);
4394 secondWindow->setDupTouchToWallpaper(true);
4395
4396 sp<FakeWindowHandle> wallpaper1 =
4397 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4398 wallpaper1->setIsWallpaper(true);
4399
4400 sp<FakeWindowHandle> wallpaper2 =
4401 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4402 wallpaper2->setIsWallpaper(true);
4403 // Add the windows to the dispatcher
4404 mDispatcher->setInputWindows(
4405 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4406
4407 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004408 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4409 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004410
4411 // Only the first window should get the down event
4412 firstWindow->consumeMotionDown();
4413 secondWindow->assertNoEvents();
4414 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4415 wallpaper2->assertNoEvents();
4416
4417 // Transfer touch focus to the second window
4418 TransferFunction f = GetParam();
4419 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4420 ASSERT_TRUE(success);
4421
4422 // The first window gets cancel and the second gets down
4423 firstWindow->consumeMotionCancel();
4424 secondWindow->consumeMotionDown();
4425 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4426 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4427
4428 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004429 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4430 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004431 // The first window gets no events and the second gets up
4432 firstWindow->assertNoEvents();
4433 secondWindow->consumeMotionUp();
4434 wallpaper1->assertNoEvents();
4435 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4436}
4437
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004438// For the cases of single pointer touch and two pointers non-split touch, the api's
4439// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4440// for the case where there are multiple pointers split across several windows.
4441INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4442 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004443 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4444 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004445 return dispatcher->transferTouch(destChannelToken,
4446 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004447 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004448 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4449 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004450 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004451 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004452 }));
4453
Svet Ganov5d3bc372020-01-26 23:11:07 -08004454TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004455 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004456
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004457 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004458 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4459 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004460 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004461
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004462 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004463 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4464 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004465 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004466
4467 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004468 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004469
4470 PointF pointInFirst = {300, 200};
4471 PointF pointInSecond = {300, 600};
4472
4473 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004474 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4475 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4476 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004477 // Only the first window should get the down event
4478 firstWindow->consumeMotionDown();
4479 secondWindow->assertNoEvents();
4480
4481 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004482 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4483 ADISPLAY_ID_DEFAULT,
4484 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004485 // The first window gets a move and the second a down
4486 firstWindow->consumeMotionMove();
4487 secondWindow->consumeMotionDown();
4488
4489 // Transfer touch focus to the second window
4490 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4491 // The first window gets cancel and the new gets pointer down (it already saw down)
4492 firstWindow->consumeMotionCancel();
4493 secondWindow->consumeMotionPointerDown(1);
4494
4495 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004496 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4497 ADISPLAY_ID_DEFAULT,
4498 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004499 // The first window gets nothing and the second gets pointer up
4500 firstWindow->assertNoEvents();
4501 secondWindow->consumeMotionPointerUp(1);
4502
4503 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004504 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4505 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004506 // The first window gets nothing and the second gets up
4507 firstWindow->assertNoEvents();
4508 secondWindow->consumeMotionUp();
4509}
4510
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004511// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4512// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4513// touch is not supported, so the touch should continue on those windows and the transferred-to
4514// window should get nothing.
4515TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4516 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4517
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004518 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004519 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4520 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004521 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004522
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004523 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004524 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4525 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004526 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004527
4528 // Add the windows to the dispatcher
4529 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4530
4531 PointF pointInFirst = {300, 200};
4532 PointF pointInSecond = {300, 600};
4533
4534 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004535 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4536 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4537 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004538 // Only the first window should get the down event
4539 firstWindow->consumeMotionDown();
4540 secondWindow->assertNoEvents();
4541
4542 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004543 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4544 ADISPLAY_ID_DEFAULT,
4545 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004546 // The first window gets a move and the second a down
4547 firstWindow->consumeMotionMove();
4548 secondWindow->consumeMotionDown();
4549
4550 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004551 const bool transferred =
4552 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004553 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4554 ASSERT_FALSE(transferred);
4555 firstWindow->assertNoEvents();
4556 secondWindow->assertNoEvents();
4557
4558 // The rest of the dispatch should proceed as normal
4559 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004560 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4561 ADISPLAY_ID_DEFAULT,
4562 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004563 // The first window gets MOVE and the second gets pointer up
4564 firstWindow->consumeMotionMove();
4565 secondWindow->consumeMotionUp();
4566
4567 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004568 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4569 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004570 // The first window gets nothing and the second gets up
4571 firstWindow->consumeMotionUp();
4572 secondWindow->assertNoEvents();
4573}
4574
Arthur Hungabbb9d82021-09-01 14:52:30 +00004575// This case will create two windows and one mirrored window on the default display and mirror
4576// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4577// the windows info of second display before default display.
4578TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4579 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4580 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004581 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004582 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004583 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004584 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004585 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004586
4587 sp<FakeWindowHandle> mirrorWindowInPrimary =
4588 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4589 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004590
4591 sp<FakeWindowHandle> firstWindowInSecondary =
4592 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4593 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004594
4595 sp<FakeWindowHandle> secondWindowInSecondary =
4596 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4597 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004598
4599 // Update window info, let it find window handle of second display first.
4600 mDispatcher->setInputWindows(
4601 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4602 {ADISPLAY_ID_DEFAULT,
4603 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4604
4605 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4606 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4607 {50, 50}))
4608 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4609
4610 // Window should receive motion event.
4611 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4612
4613 // Transfer touch focus
4614 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4615 secondWindowInPrimary->getToken()));
4616 // The first window gets cancel.
4617 firstWindowInPrimary->consumeMotionCancel();
4618 secondWindowInPrimary->consumeMotionDown();
4619
4620 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4621 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4622 ADISPLAY_ID_DEFAULT, {150, 50}))
4623 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4624 firstWindowInPrimary->assertNoEvents();
4625 secondWindowInPrimary->consumeMotionMove();
4626
4627 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4628 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4629 {150, 50}))
4630 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4631 firstWindowInPrimary->assertNoEvents();
4632 secondWindowInPrimary->consumeMotionUp();
4633}
4634
4635// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4636// 'transferTouch' api.
4637TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4638 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4639 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004640 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004641 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004642 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004643 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004644 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004645
4646 sp<FakeWindowHandle> mirrorWindowInPrimary =
4647 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4648 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004649
4650 sp<FakeWindowHandle> firstWindowInSecondary =
4651 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4652 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004653
4654 sp<FakeWindowHandle> secondWindowInSecondary =
4655 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4656 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004657
4658 // Update window info, let it find window handle of second display first.
4659 mDispatcher->setInputWindows(
4660 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4661 {ADISPLAY_ID_DEFAULT,
4662 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4663
4664 // Touch on second display.
4665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4666 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4667 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4668
4669 // Window should receive motion event.
4670 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4671
4672 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004673 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004674
4675 // The first window gets cancel.
4676 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4677 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4678
4679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4680 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4681 SECOND_DISPLAY_ID, {150, 50}))
4682 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4683 firstWindowInPrimary->assertNoEvents();
4684 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4685
4686 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4687 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4688 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4689 firstWindowInPrimary->assertNoEvents();
4690 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4691}
4692
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004693TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004694 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004695 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4696 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004697
Vishnu Nair47074b82020-08-14 11:54:47 -07004698 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004699 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004700 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004701
4702 window->consumeFocusEvent(true);
4703
Prabir Pradhan678438e2023-04-13 19:32:51 +00004704 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004705
4706 // Window should receive key down event.
4707 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004708
4709 // Should have poked user activity
4710 mFakePolicy->assertUserActivityPoked();
4711}
4712
4713TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4714 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4715 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4716 "Fake Window", ADISPLAY_ID_DEFAULT);
4717
4718 window->setDisableUserActivity(true);
4719 window->setFocusable(true);
4720 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4721 setFocusedWindow(window);
4722
4723 window->consumeFocusEvent(true);
4724
4725 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4726
4727 // Window should receive key down event.
4728 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4729
4730 // Should have poked user activity
4731 mFakePolicy->assertUserActivityNotPoked();
4732}
4733
4734TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4735 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4736 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4737 "Fake Window", ADISPLAY_ID_DEFAULT);
4738
4739 window->setFocusable(true);
4740 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4741 setFocusedWindow(window);
4742
4743 window->consumeFocusEvent(true);
4744
4745 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4746 mDispatcher->waitForIdle();
4747
4748 // System key is not passed down
4749 window->assertNoEvents();
4750
4751 // Should have poked user activity
4752 mFakePolicy->assertUserActivityPoked();
4753}
4754
4755TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4756 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4757 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4758 "Fake Window", ADISPLAY_ID_DEFAULT);
4759
4760 window->setFocusable(true);
4761 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4762 setFocusedWindow(window);
4763
4764 window->consumeFocusEvent(true);
4765
4766 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4767 mDispatcher->waitForIdle();
4768
4769 // System key is not passed down
4770 window->assertNoEvents();
4771
4772 // Should have poked user activity
4773 mFakePolicy->assertUserActivityPoked();
4774}
4775
4776TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4777 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4778 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4779 "Fake Window", ADISPLAY_ID_DEFAULT);
4780
4781 window->setDisableUserActivity(true);
4782 window->setFocusable(true);
4783 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4784 setFocusedWindow(window);
4785
4786 window->consumeFocusEvent(true);
4787
4788 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4789 mDispatcher->waitForIdle();
4790
4791 // System key is not passed down
4792 window->assertNoEvents();
4793
4794 // Should have poked user activity
4795 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004796}
4797
4798TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004799 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004800 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4801 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004802
Arthur Hung72d8dc32020-03-28 00:48:39 +00004803 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004804
Prabir Pradhan678438e2023-04-13 19:32:51 +00004805 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004806 mDispatcher->waitForIdle();
4807
4808 window->assertNoEvents();
4809}
4810
4811// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4812TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004813 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004814 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4815 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004816
Arthur Hung72d8dc32020-03-28 00:48:39 +00004817 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004818
4819 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004820 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004821 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004822 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4823 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004824
4825 // Window should receive only the motion event
4826 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4827 window->assertNoEvents(); // Key event or focus event will not be received
4828}
4829
arthurhungea3f4fc2020-12-21 23:18:53 +08004830TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4831 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4832
arthurhungea3f4fc2020-12-21 23:18:53 +08004833 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004834 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4835 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004836 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004837
arthurhungea3f4fc2020-12-21 23:18:53 +08004838 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004839 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4840 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004841 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004842
4843 // Add the windows to the dispatcher
4844 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4845
4846 PointF pointInFirst = {300, 200};
4847 PointF pointInSecond = {300, 600};
4848
4849 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004850 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4851 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4852 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004853 // Only the first window should get the down event
4854 firstWindow->consumeMotionDown();
4855 secondWindow->assertNoEvents();
4856
4857 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004858 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4859 ADISPLAY_ID_DEFAULT,
4860 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004861 // The first window gets a move and the second a down
4862 firstWindow->consumeMotionMove();
4863 secondWindow->consumeMotionDown();
4864
4865 // Send pointer cancel to the second window
4866 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004867 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004868 {pointInFirst, pointInSecond});
4869 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004870 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004871 // The first window gets move and the second gets cancel.
4872 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4873 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4874
4875 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004876 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4877 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004878 // The first window gets up and the second gets nothing.
4879 firstWindow->consumeMotionUp();
4880 secondWindow->assertNoEvents();
4881}
4882
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004883TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4884 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4885
4886 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004887 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004888 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4889 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4890 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4891 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4892
Harry Cutts33476232023-01-30 19:57:29 +00004893 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004894 window->assertNoEvents();
4895 mDispatcher->waitForIdle();
4896}
4897
chaviwd1c23182019-12-20 18:44:56 -08004898class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004899public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004900 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004901 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004902 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004903 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004904 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004905 }
4906
chaviwd1c23182019-12-20 18:44:56 -08004907 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4908
4909 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004910 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4911 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004912 }
4913
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004914 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4915
4916 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4917
chaviwd1c23182019-12-20 18:44:56 -08004918 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004919 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004920 expectedDisplayId, expectedFlags);
4921 }
4922
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004923 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004924 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004925 expectedDisplayId, expectedFlags);
4926 }
4927
chaviwd1c23182019-12-20 18:44:56 -08004928 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004929 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004930 expectedDisplayId, expectedFlags);
4931 }
4932
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004933 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004934 mInputReceiver->consumeMotionEvent(
4935 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4936 WithDisplayId(expectedDisplayId),
4937 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004938 }
4939
Arthur Hungfbfa5722021-11-16 02:45:54 +00004940 void consumeMotionPointerDown(int32_t pointerIdx) {
4941 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4942 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004943 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004944 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004945 }
4946
Evan Rosky84f07f02021-04-16 10:42:42 -07004947 MotionEvent* consumeMotion() {
4948 InputEvent* event = mInputReceiver->consume();
4949 if (!event) {
4950 ADD_FAILURE() << "No event was produced";
4951 return nullptr;
4952 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004953 if (event->getType() != InputEventType::MOTION) {
4954 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07004955 return nullptr;
4956 }
4957 return static_cast<MotionEvent*>(event);
4958 }
4959
chaviwd1c23182019-12-20 18:44:56 -08004960 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4961
4962private:
4963 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004964};
4965
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004966using InputDispatcherMonitorTest = InputDispatcherTest;
4967
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004968/**
4969 * Two entities that receive touch: A window, and a global monitor.
4970 * The touch goes to the window, and then the window disappears.
4971 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4972 * for the monitor, as well.
4973 * 1. foregroundWindow
4974 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4975 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004976TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004977 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4978 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004979 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004980
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004981 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004982
4983 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4984 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4985 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4986 {100, 200}))
4987 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4988
4989 // Both the foreground window and the global monitor should receive the touch down
4990 window->consumeMotionDown();
4991 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4992
4993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4994 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4995 ADISPLAY_ID_DEFAULT, {110, 200}))
4996 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4997
4998 window->consumeMotionMove();
4999 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5000
5001 // Now the foreground window goes away
5002 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
5003 window->consumeMotionCancel();
5004 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5005
5006 // If more events come in, there will be no more foreground window to send them to. This will
5007 // cause a cancel for the monitor, as well.
5008 ASSERT_EQ(InputEventInjectionResult::FAILED,
5009 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5010 ADISPLAY_ID_DEFAULT, {120, 200}))
5011 << "Injection should fail because the window was removed";
5012 window->assertNoEvents();
5013 // Global monitor now gets the cancel
5014 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5015}
5016
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005017TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005018 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005019 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5020 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005021 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005022
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005023 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005024
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005025 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005026 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005027 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005028 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005029 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005030}
5031
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005032TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5033 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005034
Chris Yea209fde2020-07-22 13:54:51 -07005035 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005036 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5037 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005038 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005039
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005040 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005041 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005042 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005043 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005044 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005045
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005046 // Pilfer pointers from the monitor.
5047 // This should not do anything and the window should continue to receive events.
5048 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005049
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005051 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5052 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005053 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005054
5055 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5056 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005057}
5058
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005059TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005060 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005061 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5062 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005063 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5064 window->setWindowOffset(20, 40);
5065 window->setWindowTransform(0, 1, -1, 0);
5066
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005067 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005068
5069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5070 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5071 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5072 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5073 MotionEvent* event = monitor.consumeMotion();
5074 // Even though window has transform, gesture monitor must not.
5075 ASSERT_EQ(ui::Transform(), event->getTransform());
5076}
5077
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005078TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005079 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005080 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005081
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005082 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00005083 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005084 << "Injection should fail if there is a monitor, but no touchable window";
5085 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005086}
5087
chaviw81e2bb92019-12-18 15:03:51 -08005088TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005089 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005090 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5091 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005092
Arthur Hung72d8dc32020-03-28 00:48:39 +00005093 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08005094
5095 NotifyMotionArgs motionArgs =
5096 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5097 ADISPLAY_ID_DEFAULT);
5098
Prabir Pradhan678438e2023-04-13 19:32:51 +00005099 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005100 // Window should receive motion down event.
5101 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5102
5103 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005104 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005105 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5106 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5107 motionArgs.pointerCoords[0].getX() - 10);
5108
Prabir Pradhan678438e2023-04-13 19:32:51 +00005109 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005110 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005111 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005112}
5113
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005114/**
5115 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5116 * the device default right away. In the test scenario, we check both the default value,
5117 * and the action of enabling / disabling.
5118 */
5119TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005120 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005121 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5122 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005123 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005124
5125 // Set focused application.
5126 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005127 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005128
5129 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00005130 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005131 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005132 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005133
5134 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005135 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005136 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005137 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005138
5139 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005140 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005141 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005142 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005143 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005144 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005145 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005146 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005147
5148 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005149 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005150 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005151 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005152
5153 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005154 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005155 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005156 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005157 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005158 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005159 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005160 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005161
5162 window->assertNoEvents();
5163}
5164
Gang Wange9087892020-01-07 12:17:14 -05005165TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005166 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005167 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5168 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005169
5170 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005171 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005172
Arthur Hung72d8dc32020-03-28 00:48:39 +00005173 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005174 setFocusedWindow(window);
5175
Harry Cutts33476232023-01-30 19:57:29 +00005176 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005177
Prabir Pradhan678438e2023-04-13 19:32:51 +00005178 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5179 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005180
5181 InputEvent* event = window->consume();
5182 ASSERT_NE(event, nullptr);
5183
5184 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5185 ASSERT_NE(verified, nullptr);
5186 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5187
5188 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5189 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5190 ASSERT_EQ(keyArgs.source, verified->source);
5191 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5192
5193 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5194
5195 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005196 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005197 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005198 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5199 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5200 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5201 ASSERT_EQ(0, verifiedKey.repeatCount);
5202}
5203
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005204TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005205 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005206 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5207 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005208
5209 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5210
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005211 ui::Transform transform;
5212 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5213
5214 gui::DisplayInfo displayInfo;
5215 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5216 displayInfo.transform = transform;
5217
5218 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005219
Prabir Pradhan678438e2023-04-13 19:32:51 +00005220 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005221 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5222 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005223 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005224
5225 InputEvent* event = window->consume();
5226 ASSERT_NE(event, nullptr);
5227
5228 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5229 ASSERT_NE(verified, nullptr);
5230 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5231
5232 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5233 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5234 EXPECT_EQ(motionArgs.source, verified->source);
5235 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5236
5237 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5238
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005239 const vec2 rawXY =
5240 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5241 motionArgs.pointerCoords[0].getXYValue());
5242 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5243 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005244 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005245 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005246 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005247 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5248 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5249}
5250
chaviw09c8d2d2020-08-24 15:48:26 -07005251/**
5252 * Ensure that separate calls to sign the same data are generating the same key.
5253 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5254 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5255 * tests.
5256 */
5257TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5258 KeyEvent event = getTestKeyEvent();
5259 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5260
5261 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5262 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5263 ASSERT_EQ(hmac1, hmac2);
5264}
5265
5266/**
5267 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5268 */
5269TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5270 KeyEvent event = getTestKeyEvent();
5271 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5272 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5273
5274 verifiedEvent.deviceId += 1;
5275 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5276
5277 verifiedEvent.source += 1;
5278 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5279
5280 verifiedEvent.eventTimeNanos += 1;
5281 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5282
5283 verifiedEvent.displayId += 1;
5284 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5285
5286 verifiedEvent.action += 1;
5287 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5288
5289 verifiedEvent.downTimeNanos += 1;
5290 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5291
5292 verifiedEvent.flags += 1;
5293 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5294
5295 verifiedEvent.keyCode += 1;
5296 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5297
5298 verifiedEvent.scanCode += 1;
5299 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5300
5301 verifiedEvent.metaState += 1;
5302 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5303
5304 verifiedEvent.repeatCount += 1;
5305 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5306}
5307
Vishnu Nair958da932020-08-21 17:12:37 -07005308TEST_F(InputDispatcherTest, SetFocusedWindow) {
5309 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5310 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005311 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005312 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005313 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005314 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5315
5316 // Top window is also focusable but is not granted focus.
5317 windowTop->setFocusable(true);
5318 windowSecond->setFocusable(true);
5319 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5320 setFocusedWindow(windowSecond);
5321
5322 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5324 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005325
5326 // Focused window should receive event.
5327 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5328 windowTop->assertNoEvents();
5329}
5330
5331TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5332 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5333 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005334 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005335 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5336
5337 window->setFocusable(true);
5338 // Release channel for window is no longer valid.
5339 window->releaseChannel();
5340 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5341 setFocusedWindow(window);
5342
5343 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005344 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5345 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005346
5347 // window channel is invalid, so it should not receive any input event.
5348 window->assertNoEvents();
5349}
5350
5351TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5352 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5353 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005354 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005355 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005356 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5357
Vishnu Nair958da932020-08-21 17:12:37 -07005358 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5359 setFocusedWindow(window);
5360
5361 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005362 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5363 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005364
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005365 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005366 window->assertNoEvents();
5367}
5368
5369TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5370 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5371 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005372 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005373 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005374 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005375 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5376
5377 windowTop->setFocusable(true);
5378 windowSecond->setFocusable(true);
5379 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5380 setFocusedWindow(windowTop);
5381 windowTop->consumeFocusEvent(true);
5382
Chavi Weingarten847e8512023-03-29 00:26:09 +00005383 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5384 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005385 windowSecond->consumeFocusEvent(true);
5386 windowTop->consumeFocusEvent(false);
5387
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005388 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5389 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005390
5391 // Focused window should receive event.
5392 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5393}
5394
Chavi Weingarten847e8512023-03-29 00:26:09 +00005395TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005396 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5397 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005398 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005399 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005400 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005401 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5402
5403 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005404 windowSecond->setFocusable(false);
5405 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005406 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005407 setFocusedWindow(windowTop);
5408 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005409
Chavi Weingarten847e8512023-03-29 00:26:09 +00005410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5411 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005412
5413 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005414 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005415 windowSecond->assertNoEvents();
5416}
5417
5418TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5419 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5420 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005421 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005422 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005423 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5424 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005425 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5426
5427 window->setFocusable(true);
5428 previousFocusedWindow->setFocusable(true);
5429 window->setVisible(false);
5430 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5431 setFocusedWindow(previousFocusedWindow);
5432 previousFocusedWindow->consumeFocusEvent(true);
5433
5434 // Requesting focus on invisible window takes focus from currently focused window.
5435 setFocusedWindow(window);
5436 previousFocusedWindow->consumeFocusEvent(false);
5437
5438 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005440 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5441 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005442
5443 // Window does not get focus event or key down.
5444 window->assertNoEvents();
5445
5446 // Window becomes visible.
5447 window->setVisible(true);
5448 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5449
5450 // Window receives focus event.
5451 window->consumeFocusEvent(true);
5452 // Focused window receives key down.
5453 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5454}
5455
Vishnu Nair599f1412021-06-21 10:39:58 -07005456TEST_F(InputDispatcherTest, DisplayRemoved) {
5457 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5458 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005459 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005460 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5461
5462 // window is granted focus.
5463 window->setFocusable(true);
5464 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5465 setFocusedWindow(window);
5466 window->consumeFocusEvent(true);
5467
5468 // When a display is removed window loses focus.
5469 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5470 window->consumeFocusEvent(false);
5471}
5472
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005473/**
5474 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5475 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5476 * of the 'slipperyEnterWindow'.
5477 *
5478 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5479 * a way so that the touched location is no longer covered by the top window.
5480 *
5481 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5482 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5483 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5484 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5485 * with ACTION_DOWN).
5486 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5487 * window moved itself away from the touched location and had Flag::SLIPPERY.
5488 *
5489 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5490 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5491 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5492 *
5493 * In this test, we ensure that the event received by the bottom window has
5494 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5495 */
5496TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00005497 constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
5498 constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005499
5500 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5501 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5502
5503 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005504 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005505 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005506 // Make sure this one overlaps the bottom window
5507 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5508 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5509 // one. Windows with the same owner are not considered to be occluding each other.
5510 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5511
5512 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005513 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005514 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5515
5516 mDispatcher->setInputWindows(
5517 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5518
5519 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005520 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5521 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5522 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005523 slipperyExitWindow->consumeMotionDown();
5524 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5525 mDispatcher->setInputWindows(
5526 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5527
Prabir Pradhan678438e2023-04-13 19:32:51 +00005528 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5529 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5530 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005531
5532 slipperyExitWindow->consumeMotionCancel();
5533
5534 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5535 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5536}
5537
Garfield Tan1c7bc862020-01-28 13:24:04 -08005538class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5539protected:
5540 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5541 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5542
Chris Yea209fde2020-07-22 13:54:51 -07005543 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005544 sp<FakeWindowHandle> mWindow;
5545
5546 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005547 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005548 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Prabir Pradhana41d2442023-04-20 21:30:40 +00005549 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Prabir Pradhan87112a72023-04-20 19:13:39 +00005550 mDispatcher->requestRefreshConfiguration();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005551 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
5552 ASSERT_EQ(OK, mDispatcher->start());
5553
5554 setUpWindow();
5555 }
5556
5557 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005558 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005559 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005560
Vishnu Nair47074b82020-08-14 11:54:47 -07005561 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005562 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005563 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005564 mWindow->consumeFocusEvent(true);
5565 }
5566
Chris Ye2ad95392020-09-01 13:44:44 -07005567 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005568 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005569 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005570 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005571 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005572
5573 // Window should receive key down event.
5574 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5575 }
5576
5577 void expectKeyRepeatOnce(int32_t repeatCount) {
5578 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5579 InputEvent* repeatEvent = mWindow->consume();
5580 ASSERT_NE(nullptr, repeatEvent);
5581
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005582 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005583
5584 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5585 uint32_t eventAction = repeatKeyEvent->getAction();
5586 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5587 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5588 }
5589
Chris Ye2ad95392020-09-01 13:44:44 -07005590 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005591 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005592 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005593 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005594 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005595
5596 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005597 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005598 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005599 }
5600};
5601
5602TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005603 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005604 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5605 expectKeyRepeatOnce(repeatCount);
5606 }
5607}
5608
5609TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005610 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005611 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5612 expectKeyRepeatOnce(repeatCount);
5613 }
Harry Cutts33476232023-01-30 19:57:29 +00005614 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005615 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005616 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5617 expectKeyRepeatOnce(repeatCount);
5618 }
5619}
5620
5621TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005622 sendAndConsumeKeyDown(/*deviceId=*/1);
5623 expectKeyRepeatOnce(/*repeatCount=*/1);
5624 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005625 mWindow->assertNoEvents();
5626}
5627
5628TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005629 sendAndConsumeKeyDown(/*deviceId=*/1);
5630 expectKeyRepeatOnce(/*repeatCount=*/1);
5631 sendAndConsumeKeyDown(/*deviceId=*/2);
5632 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005633 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005634 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005635 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005636 expectKeyRepeatOnce(/*repeatCount=*/2);
5637 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005638 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005639 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005640 mWindow->assertNoEvents();
5641}
5642
5643TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005644 sendAndConsumeKeyDown(/*deviceId=*/1);
5645 expectKeyRepeatOnce(/*repeatCount=*/1);
5646 sendAndConsumeKeyDown(/*deviceId=*/2);
5647 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005648 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005649 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005650 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005651 mWindow->assertNoEvents();
5652}
5653
liushenxiang42232912021-05-21 20:24:09 +08005654TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5655 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005656 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005657 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005658 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5659 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5660 mWindow->assertNoEvents();
5661}
5662
Garfield Tan1c7bc862020-01-28 13:24:04 -08005663TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005664 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005665 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005666 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5667 InputEvent* repeatEvent = mWindow->consume();
5668 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5669 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5670 IdGenerator::getSource(repeatEvent->getId()));
5671 }
5672}
5673
5674TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005675 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005676 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005677
5678 std::unordered_set<int32_t> idSet;
5679 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5680 InputEvent* repeatEvent = mWindow->consume();
5681 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5682 int32_t id = repeatEvent->getId();
5683 EXPECT_EQ(idSet.end(), idSet.find(id));
5684 idSet.insert(id);
5685 }
5686}
5687
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005688/* Test InputDispatcher for MultiDisplay */
5689class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5690public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005691 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005692 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005693
Chris Yea209fde2020-07-22 13:54:51 -07005694 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005695 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005696 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005697
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005698 // Set focus window for primary display, but focused display would be second one.
5699 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005700 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005701 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005702 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005703 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005704
Chris Yea209fde2020-07-22 13:54:51 -07005705 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005706 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005707 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005708 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005709 // Set focus display to second one.
5710 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5711 // Set focus window for second display.
5712 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005713 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005714 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005715 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005716 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005717 }
5718
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005719 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005720 InputDispatcherTest::TearDown();
5721
Chris Yea209fde2020-07-22 13:54:51 -07005722 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005723 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005724 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005725 windowInSecondary.clear();
5726 }
5727
5728protected:
Chris Yea209fde2020-07-22 13:54:51 -07005729 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005730 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005731 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005732 sp<FakeWindowHandle> windowInSecondary;
5733};
5734
5735TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5736 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005737 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5738 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005740 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005741 windowInSecondary->assertNoEvents();
5742
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005743 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5745 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5746 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005747 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005748 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005749}
5750
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005751TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005752 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5754 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005755 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005756 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005757 windowInSecondary->assertNoEvents();
5758
5759 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005761 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005762 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005763 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005764
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005765 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005766 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005767
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005768 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005769 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005770 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005771
5772 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005773 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005774 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005775 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005776 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005777 windowInSecondary->assertNoEvents();
5778}
5779
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005780// Test per-display input monitors for motion event.
5781TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005782 FakeMonitorReceiver monitorInPrimary =
5783 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5784 FakeMonitorReceiver monitorInSecondary =
5785 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005786
5787 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005788 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5789 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5790 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005791 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005792 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005793 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005794 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005795
5796 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005797 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5798 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5799 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005800 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005801 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005802 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005803 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005804
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005805 // Lift up the touch from the second display
5806 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5807 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5808 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5809 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5810 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5811
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005812 // Test inject a non-pointer motion event.
5813 // If specific a display, it will dispatch to the focused window of particular display,
5814 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005815 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5816 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5817 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005818 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005819 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005820 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005821 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005822}
5823
5824// Test per-display input monitors for key event.
5825TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005826 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005827 FakeMonitorReceiver monitorInPrimary =
5828 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5829 FakeMonitorReceiver monitorInSecondary =
5830 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005831
5832 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005833 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5834 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005835 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005836 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005837 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005838 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005839}
5840
Vishnu Nair958da932020-08-21 17:12:37 -07005841TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
5842 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005843 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005844 secondWindowInPrimary->setFocusable(true);
5845 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
5846 setFocusedWindow(secondWindowInPrimary);
5847 windowInPrimary->consumeFocusEvent(false);
5848 secondWindowInPrimary->consumeFocusEvent(true);
5849
5850 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
5852 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005853 windowInPrimary->assertNoEvents();
5854 windowInSecondary->assertNoEvents();
5855 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5856}
5857
Arthur Hungdfd528e2021-12-08 13:23:04 +00005858TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
5859 FakeMonitorReceiver monitorInPrimary =
5860 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5861 FakeMonitorReceiver monitorInSecondary =
5862 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
5863
5864 // Test touch down on primary display.
5865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5866 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5867 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5868 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5869 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5870
5871 // Test touch down on second display.
5872 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5873 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5874 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5875 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
5876 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
5877
5878 // Trigger cancel touch.
5879 mDispatcher->cancelCurrentTouch();
5880 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5881 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5882 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
5883 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
5884
5885 // Test inject a move motion event, no window/monitor should receive the event.
5886 ASSERT_EQ(InputEventInjectionResult::FAILED,
5887 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5888 ADISPLAY_ID_DEFAULT, {110, 200}))
5889 << "Inject motion event should return InputEventInjectionResult::FAILED";
5890 windowInPrimary->assertNoEvents();
5891 monitorInPrimary.assertNoEvents();
5892
5893 ASSERT_EQ(InputEventInjectionResult::FAILED,
5894 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5895 SECOND_DISPLAY_ID, {110, 200}))
5896 << "Inject motion event should return InputEventInjectionResult::FAILED";
5897 windowInSecondary->assertNoEvents();
5898 monitorInSecondary.assertNoEvents();
5899}
5900
Jackal Guof9696682018-10-05 12:23:23 +08005901class InputFilterTest : public InputDispatcherTest {
5902protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005903 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
5904 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08005905 NotifyMotionArgs motionArgs;
5906
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005907 motionArgs =
5908 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005909 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005910 motionArgs =
5911 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005912 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005913 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005914 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005915 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
5916 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08005917 } else {
5918 mFakePolicy->assertFilterInputEventWasNotCalled();
5919 }
5920 }
5921
5922 void testNotifyKey(bool expectToBeFiltered) {
5923 NotifyKeyArgs keyArgs;
5924
5925 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005926 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08005927 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005928 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005929 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005930
5931 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08005932 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08005933 } else {
5934 mFakePolicy->assertFilterInputEventWasNotCalled();
5935 }
5936 }
5937};
5938
5939// Test InputFilter for MotionEvent
5940TEST_F(InputFilterTest, MotionEvent_InputFilter) {
5941 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
5942 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5943 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5944
5945 // Enable InputFilter
5946 mDispatcher->setInputFilterEnabled(true);
5947 // Test touch on both primary and second display, and check if both events are filtered.
5948 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
5949 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
5950
5951 // Disable InputFilter
5952 mDispatcher->setInputFilterEnabled(false);
5953 // Test touch on both primary and second display, and check if both events aren't filtered.
5954 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5955 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5956}
5957
5958// Test InputFilter for KeyEvent
5959TEST_F(InputFilterTest, KeyEvent_InputFilter) {
5960 // Since the InputFilter is disabled by default, check if key event aren't filtered.
5961 testNotifyKey(/*expectToBeFiltered*/ false);
5962
5963 // Enable InputFilter
5964 mDispatcher->setInputFilterEnabled(true);
5965 // Send a key event, and check if it is filtered.
5966 testNotifyKey(/*expectToBeFiltered*/ true);
5967
5968 // Disable InputFilter
5969 mDispatcher->setInputFilterEnabled(false);
5970 // Send a key event, and check if it isn't filtered.
5971 testNotifyKey(/*expectToBeFiltered*/ false);
5972}
5973
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005974// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
5975// logical display coordinate space.
5976TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
5977 ui::Transform firstDisplayTransform;
5978 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5979 ui::Transform secondDisplayTransform;
5980 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
5981
5982 std::vector<gui::DisplayInfo> displayInfos(2);
5983 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
5984 displayInfos[0].transform = firstDisplayTransform;
5985 displayInfos[1].displayId = SECOND_DISPLAY_ID;
5986 displayInfos[1].transform = secondDisplayTransform;
5987
5988 mDispatcher->onWindowInfosChanged({}, displayInfos);
5989
5990 // Enable InputFilter
5991 mDispatcher->setInputFilterEnabled(true);
5992
5993 // Ensure the correct transforms are used for the displays.
5994 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
5995 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
5996}
5997
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005998class InputFilterInjectionPolicyTest : public InputDispatcherTest {
5999protected:
6000 virtual void SetUp() override {
6001 InputDispatcherTest::SetUp();
6002
6003 /**
6004 * We don't need to enable input filter to test the injected event policy, but we enabled it
6005 * here to make the tests more realistic, since this policy only matters when inputfilter is
6006 * on.
6007 */
6008 mDispatcher->setInputFilterEnabled(true);
6009
6010 std::shared_ptr<InputApplicationHandle> application =
6011 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006012 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6013 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006014
6015 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6016 mWindow->setFocusable(true);
6017 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6018 setFocusedWindow(mWindow);
6019 mWindow->consumeFocusEvent(true);
6020 }
6021
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006022 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6023 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006024 KeyEvent event;
6025
6026 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6027 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6028 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006029 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006030 const int32_t additionalPolicyFlags =
6031 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006033 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006034 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6035 policyFlags | additionalPolicyFlags));
6036
6037 InputEvent* received = mWindow->consume();
6038 ASSERT_NE(nullptr, received);
6039 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006040 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006041 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
6042 ASSERT_EQ(flags, keyEvent.getFlags());
6043 }
6044
6045 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6046 int32_t flags) {
6047 MotionEvent event;
6048 PointerProperties pointerProperties[1];
6049 PointerCoords pointerCoords[1];
6050 pointerProperties[0].clear();
6051 pointerProperties[0].id = 0;
6052 pointerCoords[0].clear();
6053 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6054 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6055
6056 ui::Transform identityTransform;
6057 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6058 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6059 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6060 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6061 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006062 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006063 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006064 /*pointerCount*/ 1, pointerProperties, pointerCoords);
6065
6066 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006068 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006069 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6070 policyFlags | additionalPolicyFlags));
6071
6072 InputEvent* received = mWindow->consume();
6073 ASSERT_NE(nullptr, received);
6074 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006075 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006076 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
6077 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006078 }
6079
6080private:
6081 sp<FakeWindowHandle> mWindow;
6082};
6083
6084TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006085 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6086 // filter. Without it, the event will no different from a regularly injected event, and the
6087 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006088 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6089 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006090}
6091
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006092TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006093 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006094 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006095 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6096}
6097
6098TEST_F(InputFilterInjectionPolicyTest,
6099 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6100 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006101 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006102 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006103}
6104
6105TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006106 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6107 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006108}
6109
chaviwfd6d3512019-03-25 13:23:49 -07006110class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006111 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006112 InputDispatcherTest::SetUp();
6113
Chris Yea209fde2020-07-22 13:54:51 -07006114 std::shared_ptr<FakeApplicationHandle> application =
6115 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006116 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006117 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006118 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006119
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006120 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006121 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006122 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006123
6124 // Set focused application.
6125 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006126 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006127
6128 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00006129 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006130 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006131 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006132 }
6133
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006134 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006135 InputDispatcherTest::TearDown();
6136
6137 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006138 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006139 }
6140
6141protected:
6142 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006143 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006144 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006145};
6146
6147// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6148// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6149// the onPointerDownOutsideFocus callback.
6150TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006151 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006152 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6153 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006154 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006155 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006156
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006157 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006158 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6159}
6160
6161// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6162// DOWN on the window that doesn't have focus. Ensure no window received the
6163// onPointerDownOutsideFocus callback.
6164TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006166 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006167 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006168 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006169
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006170 ASSERT_TRUE(mDispatcher->waitForIdle());
6171 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006172}
6173
6174// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6175// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6176TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6178 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006179 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006180 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006181
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006182 ASSERT_TRUE(mDispatcher->waitForIdle());
6183 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006184}
6185
6186// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6187// DOWN on the window that already has focus. Ensure no window received the
6188// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006189TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006191 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006192 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006193 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006194 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006195
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006196 ASSERT_TRUE(mDispatcher->waitForIdle());
6197 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006198}
6199
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006200// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6201// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6202TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6203 const MotionEvent event =
6204 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6205 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006206 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006207 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6208 .build();
6209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6210 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6211 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6212
6213 ASSERT_TRUE(mDispatcher->waitForIdle());
6214 mFakePolicy->assertOnPointerDownWasNotCalled();
6215 // Ensure that the unfocused window did not receive any FOCUS events.
6216 mUnfocusedWindow->assertNoEvents();
6217}
6218
chaviwaf87b3e2019-10-01 16:59:28 -07006219// These tests ensures we can send touch events to a single client when there are multiple input
6220// windows that point to the same client token.
6221class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6222 virtual void SetUp() override {
6223 InputDispatcherTest::SetUp();
6224
Chris Yea209fde2020-07-22 13:54:51 -07006225 std::shared_ptr<FakeApplicationHandle> application =
6226 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006227 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6228 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006229 mWindow1->setFrame(Rect(0, 0, 100, 100));
6230
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006231 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6232 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006233 mWindow2->setFrame(Rect(100, 100, 200, 200));
6234
Arthur Hung72d8dc32020-03-28 00:48:39 +00006235 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006236 }
6237
6238protected:
6239 sp<FakeWindowHandle> mWindow1;
6240 sp<FakeWindowHandle> mWindow2;
6241
6242 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006243 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006244 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6245 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006246 }
6247
6248 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6249 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006250 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006251 InputEvent* event = window->consume();
6252
6253 ASSERT_NE(nullptr, event) << name.c_str()
6254 << ": consumer should have returned non-NULL event.";
6255
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006256 ASSERT_EQ(InputEventType::MOTION, event->getType())
6257 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006258
6259 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006260 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006261 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006262
6263 for (size_t i = 0; i < points.size(); i++) {
6264 float expectedX = points[i].x;
6265 float expectedY = points[i].y;
6266
6267 EXPECT_EQ(expectedX, motionEvent.getX(i))
6268 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6269 << ", got " << motionEvent.getX(i);
6270 EXPECT_EQ(expectedY, motionEvent.getY(i))
6271 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6272 << ", got " << motionEvent.getY(i);
6273 }
6274 }
chaviw9eaa22c2020-07-01 16:21:27 -07006275
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006276 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006277 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006278 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6279 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006280
6281 // Always consume from window1 since it's the window that has the InputReceiver
6282 consumeMotionEvent(mWindow1, action, expectedPoints);
6283 }
chaviwaf87b3e2019-10-01 16:59:28 -07006284};
6285
6286TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6287 // Touch Window 1
6288 PointF touchedPoint = {10, 10};
6289 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006290 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006291
6292 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006293 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006294
6295 // Touch Window 2
6296 touchedPoint = {150, 150};
6297 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006298 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006299}
6300
chaviw9eaa22c2020-07-01 16:21:27 -07006301TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6302 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006303 mWindow2->setWindowScale(0.5f, 0.5f);
6304
6305 // Touch Window 1
6306 PointF touchedPoint = {10, 10};
6307 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006308 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006309 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006310 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006311
6312 // Touch Window 2
6313 touchedPoint = {150, 150};
6314 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006315 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6316 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006317
chaviw9eaa22c2020-07-01 16:21:27 -07006318 // Update the transform so rotation is set
6319 mWindow2->setWindowTransform(0, -1, 1, 0);
6320 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6321 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006322}
6323
chaviw9eaa22c2020-07-01 16:21:27 -07006324TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006325 mWindow2->setWindowScale(0.5f, 0.5f);
6326
6327 // Touch Window 1
6328 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6329 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006330 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006331
6332 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006333 touchedPoints.push_back(PointF{150, 150});
6334 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006335 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006336
chaviw9eaa22c2020-07-01 16:21:27 -07006337 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006338 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006339 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006340
chaviw9eaa22c2020-07-01 16:21:27 -07006341 // Update the transform so rotation is set for Window 2
6342 mWindow2->setWindowTransform(0, -1, 1, 0);
6343 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006344 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006345}
6346
chaviw9eaa22c2020-07-01 16:21:27 -07006347TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006348 mWindow2->setWindowScale(0.5f, 0.5f);
6349
6350 // Touch Window 1
6351 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6352 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006353 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006354
6355 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006356 touchedPoints.push_back(PointF{150, 150});
6357 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006358
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006359 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006360
6361 // Move both windows
6362 touchedPoints = {{20, 20}, {175, 175}};
6363 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6364 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6365
chaviw9eaa22c2020-07-01 16:21:27 -07006366 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006367
chaviw9eaa22c2020-07-01 16:21:27 -07006368 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006369 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006370 expectedPoints.pop_back();
6371
6372 // Touch Window 2
6373 mWindow2->setWindowTransform(0, -1, 1, 0);
6374 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006375 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006376
6377 // Move both windows
6378 touchedPoints = {{20, 20}, {175, 175}};
6379 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6380 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6381
6382 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006383}
6384
6385TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6386 mWindow1->setWindowScale(0.5f, 0.5f);
6387
6388 // Touch Window 1
6389 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6390 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006391 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006392
6393 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006394 touchedPoints.push_back(PointF{150, 150});
6395 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006396
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006397 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006398
6399 // Move both windows
6400 touchedPoints = {{20, 20}, {175, 175}};
6401 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6402 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6403
chaviw9eaa22c2020-07-01 16:21:27 -07006404 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006405}
6406
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006407/**
6408 * When one of the windows is slippery, the touch should not slip into the other window with the
6409 * same input channel.
6410 */
6411TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6412 mWindow1->setSlippery(true);
6413 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6414
6415 // Touch down in window 1
6416 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6417 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6418 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6419
6420 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6421 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6422 // getting generated.
6423 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6424 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6425
6426 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6427}
6428
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006429class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6430 virtual void SetUp() override {
6431 InputDispatcherTest::SetUp();
6432
Chris Yea209fde2020-07-22 13:54:51 -07006433 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006434 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006435 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6436 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006437 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006438 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006439 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006440
6441 // Set focused application.
6442 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6443
6444 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006445 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006446 mWindow->consumeFocusEvent(true);
6447 }
6448
6449 virtual void TearDown() override {
6450 InputDispatcherTest::TearDown();
6451 mWindow.clear();
6452 }
6453
6454protected:
Chris Yea209fde2020-07-22 13:54:51 -07006455 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006456 sp<FakeWindowHandle> mWindow;
6457 static constexpr PointF WINDOW_LOCATION = {20, 20};
6458
6459 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006461 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6462 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006463 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006464 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6465 WINDOW_LOCATION));
6466 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006467
6468 sp<FakeWindowHandle> addSpyWindow() {
6469 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006470 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006471 spy->setTrustedOverlay(true);
6472 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006473 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006474 spy->setDispatchingTimeout(30ms);
6475 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6476 return spy;
6477 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006478};
6479
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006480// Send a tap and respond, which should not cause an ANR.
6481TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6482 tapOnWindow();
6483 mWindow->consumeMotionDown();
6484 mWindow->consumeMotionUp();
6485 ASSERT_TRUE(mDispatcher->waitForIdle());
6486 mFakePolicy->assertNotifyAnrWasNotCalled();
6487}
6488
6489// Send a regular key and respond, which should not cause an ANR.
6490TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006491 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006492 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6493 ASSERT_TRUE(mDispatcher->waitForIdle());
6494 mFakePolicy->assertNotifyAnrWasNotCalled();
6495}
6496
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006497TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6498 mWindow->setFocusable(false);
6499 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6500 mWindow->consumeFocusEvent(false);
6501
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006502 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006503 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6504 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6505 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006506 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006507 // Key will not go to window because we have no focused window.
6508 // The 'no focused window' ANR timer should start instead.
6509
6510 // Now, the focused application goes away.
6511 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6512 // The key should get dropped and there should be no ANR.
6513
6514 ASSERT_TRUE(mDispatcher->waitForIdle());
6515 mFakePolicy->assertNotifyAnrWasNotCalled();
6516}
6517
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006518// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006519// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6520// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006521TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006523 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6524 WINDOW_LOCATION));
6525
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006526 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6527 ASSERT_TRUE(sequenceNum);
6528 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006529 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006530
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006531 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006532 mWindow->consumeMotionEvent(
6533 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006534 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006535 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006536}
6537
6538// Send a key to the app and have the app not respond right away.
6539TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6540 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006541 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006542 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6543 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006544 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006545 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006546 ASSERT_TRUE(mDispatcher->waitForIdle());
6547}
6548
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006549// We have a focused application, but no focused window
6550TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006551 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006552 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6553 mWindow->consumeFocusEvent(false);
6554
6555 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006556 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006557 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6558 WINDOW_LOCATION));
6559 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6560 mDispatcher->waitForIdle();
6561 mFakePolicy->assertNotifyAnrWasNotCalled();
6562
6563 // Once a focused event arrives, we get an ANR for this application
6564 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6565 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006566 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006567 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6568 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006569 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006570 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006571 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006572 ASSERT_TRUE(mDispatcher->waitForIdle());
6573}
6574
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006575/**
6576 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6577 * there will not be an ANR.
6578 */
6579TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6580 mWindow->setFocusable(false);
6581 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6582 mWindow->consumeFocusEvent(false);
6583
6584 KeyEvent event;
6585 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6586 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6587
6588 // Define a valid key down event that is stale (too old).
6589 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6590 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006591 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006592
6593 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6594
6595 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006596 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006597 InputEventInjectionSync::WAIT_FOR_RESULT,
6598 INJECT_EVENT_TIMEOUT, policyFlags);
6599 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6600 << "Injection should fail because the event is stale";
6601
6602 ASSERT_TRUE(mDispatcher->waitForIdle());
6603 mFakePolicy->assertNotifyAnrWasNotCalled();
6604 mWindow->assertNoEvents();
6605}
6606
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006607// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006608// Make sure that we don't notify policy twice about the same ANR.
6609TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006610 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006611 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6612 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006613
6614 // Once a focused event arrives, we get an ANR for this application
6615 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6616 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006617 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006618 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6619 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006620 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006621 const std::chrono::duration appTimeout =
6622 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6623 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006624
Vishnu Naire4df8752022-09-08 09:17:55 -07006625 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006626 // ANR should not be raised again. It is up to policy to do that if it desires.
6627 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006628
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006629 // If we now get a focused window, the ANR should stop, but the policy handles that via
6630 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006631 ASSERT_TRUE(mDispatcher->waitForIdle());
6632}
6633
6634// We have a focused application, but no focused window
6635TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006636 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006637 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6638 mWindow->consumeFocusEvent(false);
6639
6640 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006641 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006642 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006643 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6644 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006645
Vishnu Naire4df8752022-09-08 09:17:55 -07006646 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6647 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006648
6649 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006650 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006651 ASSERT_TRUE(mDispatcher->waitForIdle());
6652 mWindow->assertNoEvents();
6653}
6654
6655/**
6656 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6657 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6658 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6659 * the ANR mechanism should still work.
6660 *
6661 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6662 * DOWN event, while not responding on the second one.
6663 */
6664TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6665 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6666 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6667 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6668 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6669 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006670 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006671
6672 // Now send ACTION_UP, with identical timestamp
6673 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6674 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6675 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6676 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006677 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006678
6679 // We have now sent down and up. Let's consume first event and then ANR on the second.
6680 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6681 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006682 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006683}
6684
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006685// A spy window can receive an ANR
6686TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6687 sp<FakeWindowHandle> spy = addSpyWindow();
6688
6689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6690 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6691 WINDOW_LOCATION));
6692 mWindow->consumeMotionDown();
6693
6694 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6695 ASSERT_TRUE(sequenceNum);
6696 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006697 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006698
6699 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006700 spy->consumeMotionEvent(
6701 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006702 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006703 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006704}
6705
6706// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006707// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006708TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6709 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006710
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006711 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6712 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006713 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006715
6716 // Stuck on the ACTION_UP
6717 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006718 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006719
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006720 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006721 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006722 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6723 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006724
6725 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6726 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006727 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006728 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006729 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006730}
6731
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006732// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006733// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006734TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6735 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006736
6737 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006738 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6739 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006740
6741 mWindow->consumeMotionDown();
6742 // Stuck on the ACTION_UP
6743 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006744 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006745
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006746 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006747 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006748 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6749 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006750
6751 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6752 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006753 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006754 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006755 spy->assertNoEvents();
6756}
6757
6758TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6759 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6760
6761 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6762
6763 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6764 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6765 WINDOW_LOCATION));
6766
6767 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6768 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6769 ASSERT_TRUE(consumeSeq);
6770
Prabir Pradhanedd96402022-02-15 01:46:16 -08006771 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006772
6773 monitor.finishEvent(*consumeSeq);
6774 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6775
6776 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006777 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006778}
6779
6780// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6781// process events, you don't get an anr. When the window later becomes unresponsive again, you
6782// get an ANR again.
6783// 1. tap -> block on ACTION_UP -> receive ANR
6784// 2. consume all pending events (= queue becomes healthy again)
6785// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6786TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6787 tapOnWindow();
6788
6789 mWindow->consumeMotionDown();
6790 // Block on ACTION_UP
6791 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006792 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006793 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6794 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006795 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006796 mWindow->assertNoEvents();
6797
6798 tapOnWindow();
6799 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006800 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006801 mWindow->consumeMotionUp();
6802
6803 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006804 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006805 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006806 mWindow->assertNoEvents();
6807}
6808
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006809// If a connection remains unresponsive for a while, make sure policy is only notified once about
6810// it.
6811TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006812 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006813 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6814 WINDOW_LOCATION));
6815
6816 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006817 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006818 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006819 // 'notifyConnectionUnresponsive' should only be called once per connection
6820 mFakePolicy->assertNotifyAnrWasNotCalled();
6821 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006822 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006823 mWindow->consumeMotionEvent(
6824 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006825 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006826 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006827 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006828 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006829}
6830
6831/**
6832 * If a window is processing a motion event, and then a key event comes in, the key event should
6833 * not to to the focused window until the motion is processed.
6834 *
6835 * Warning!!!
6836 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
6837 * and the injection timeout that we specify when injecting the key.
6838 * We must have the injection timeout (10ms) be smaller than
6839 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
6840 *
6841 * If that value changes, this test should also change.
6842 */
6843TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
6844 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6845 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6846
6847 tapOnWindow();
6848 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6849 ASSERT_TRUE(downSequenceNum);
6850 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6851 ASSERT_TRUE(upSequenceNum);
6852 // Don't finish the events yet, and send a key
6853 // Injection will "succeed" because we will eventually give up and send the key to the focused
6854 // window even if motions are still being processed. But because the injection timeout is short,
6855 // we will receive INJECTION_TIMED_OUT as the result.
6856
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006857 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006858 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006859 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6860 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006861 // Key will not be sent to the window, yet, because the window is still processing events
6862 // and the key remains pending, waiting for the touch events to be processed
6863 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6864 ASSERT_FALSE(keySequenceNum);
6865
6866 std::this_thread::sleep_for(500ms);
6867 // if we wait long enough though, dispatcher will give up, and still send the key
6868 // to the focused window, even though we have not yet finished the motion event
6869 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6870 mWindow->finishEvent(*downSequenceNum);
6871 mWindow->finishEvent(*upSequenceNum);
6872}
6873
6874/**
6875 * If a window is processing a motion event, and then a key event comes in, the key event should
6876 * not go to the focused window until the motion is processed.
6877 * If then a new motion comes in, then the pending key event should be going to the currently
6878 * focused window right away.
6879 */
6880TEST_F(InputDispatcherSingleWindowAnr,
6881 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
6882 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6883 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6884
6885 tapOnWindow();
6886 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6887 ASSERT_TRUE(downSequenceNum);
6888 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6889 ASSERT_TRUE(upSequenceNum);
6890 // Don't finish the events yet, and send a key
6891 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006893 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6894 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006895 // At this point, key is still pending, and should not be sent to the application yet.
6896 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6897 ASSERT_FALSE(keySequenceNum);
6898
6899 // Now tap down again. It should cause the pending key to go to the focused window right away.
6900 tapOnWindow();
6901 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
6902 // the other events yet. We can finish events in any order.
6903 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
6904 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
6905 mWindow->consumeMotionDown();
6906 mWindow->consumeMotionUp();
6907 mWindow->assertNoEvents();
6908}
6909
6910class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
6911 virtual void SetUp() override {
6912 InputDispatcherTest::SetUp();
6913
Chris Yea209fde2020-07-22 13:54:51 -07006914 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006915 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006916 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
6917 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006918 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006919 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006920 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006921
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006922 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
6923 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006924 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006925 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006926
6927 // Set focused application.
6928 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07006929 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006930
6931 // Expect one focus window exist in display.
6932 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006933 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006934 mFocusedWindow->consumeFocusEvent(true);
6935 }
6936
6937 virtual void TearDown() override {
6938 InputDispatcherTest::TearDown();
6939
6940 mUnfocusedWindow.clear();
6941 mFocusedWindow.clear();
6942 }
6943
6944protected:
Chris Yea209fde2020-07-22 13:54:51 -07006945 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006946 sp<FakeWindowHandle> mUnfocusedWindow;
6947 sp<FakeWindowHandle> mFocusedWindow;
6948 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
6949 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
6950 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
6951
6952 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
6953
6954 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
6955
6956private:
6957 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006959 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6960 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006962 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6963 location));
6964 }
6965};
6966
6967// If we have 2 windows that are both unresponsive, the one with the shortest timeout
6968// should be ANR'd first.
6969TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006970 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006971 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6972 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006973 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006974 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006975 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006976 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006977 // We consumed all events, so no ANR
6978 ASSERT_TRUE(mDispatcher->waitForIdle());
6979 mFakePolicy->assertNotifyAnrWasNotCalled();
6980
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006982 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6983 FOCUSED_WINDOW_LOCATION));
6984 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
6985 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006986
6987 const std::chrono::duration timeout =
6988 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006989 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006990 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
6991 // sequence to make it consistent
6992 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006993 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006994 mFocusedWindow->consumeMotionDown();
6995 // This cancel is generated because the connection was unresponsive
6996 mFocusedWindow->consumeMotionCancel();
6997 mFocusedWindow->assertNoEvents();
6998 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006999 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007000 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7001 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007002 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007003}
7004
7005// If we have 2 windows with identical timeouts that are both unresponsive,
7006// it doesn't matter which order they should have ANR.
7007// But we should receive ANR for both.
7008TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7009 // Set the timeout for unfocused window to match the focused window
7010 mUnfocusedWindow->setDispatchingTimeout(10ms);
7011 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7012
7013 tapOnFocusedWindow();
7014 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08007015 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
7016 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
7017 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007018
7019 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007020 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
7021 mFocusedWindow->getToken() == anrConnectionToken2);
7022 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
7023 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007024
7025 ASSERT_TRUE(mDispatcher->waitForIdle());
7026 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007027
7028 mFocusedWindow->consumeMotionDown();
7029 mFocusedWindow->consumeMotionUp();
7030 mUnfocusedWindow->consumeMotionOutside();
7031
Prabir Pradhanedd96402022-02-15 01:46:16 -08007032 sp<IBinder> responsiveToken1, responsiveToken2;
7033 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
7034 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007035
7036 // Both applications should be marked as responsive, in any order
7037 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
7038 mFocusedWindow->getToken() == responsiveToken2);
7039 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
7040 mUnfocusedWindow->getToken() == responsiveToken2);
7041 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007042}
7043
7044// If a window is already not responding, the second tap on the same window should be ignored.
7045// We should also log an error to account for the dropped event (not tested here).
7046// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7047TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7048 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007049 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007050 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007051 // Receive the events, but don't respond
7052 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7053 ASSERT_TRUE(downEventSequenceNum);
7054 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7055 ASSERT_TRUE(upEventSequenceNum);
7056 const std::chrono::duration timeout =
7057 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007058 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007059
7060 // Tap once again
7061 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007062 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007063 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7064 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007065 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007066 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7067 FOCUSED_WINDOW_LOCATION));
7068 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7069 // valid touch target
7070 mUnfocusedWindow->assertNoEvents();
7071
7072 // Consume the first tap
7073 mFocusedWindow->finishEvent(*downEventSequenceNum);
7074 mFocusedWindow->finishEvent(*upEventSequenceNum);
7075 ASSERT_TRUE(mDispatcher->waitForIdle());
7076 // The second tap did not go to the focused window
7077 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007078 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007079 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7080 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007081 mFakePolicy->assertNotifyAnrWasNotCalled();
7082}
7083
7084// If you tap outside of all windows, there will not be ANR
7085TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007086 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007087 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7088 LOCATION_OUTSIDE_ALL_WINDOWS));
7089 ASSERT_TRUE(mDispatcher->waitForIdle());
7090 mFakePolicy->assertNotifyAnrWasNotCalled();
7091}
7092
7093// Since the focused window is paused, tapping on it should not produce any events
7094TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7095 mFocusedWindow->setPaused(true);
7096 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7097
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007098 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007099 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7100 FOCUSED_WINDOW_LOCATION));
7101
7102 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7103 ASSERT_TRUE(mDispatcher->waitForIdle());
7104 // Should not ANR because the window is paused, and touches shouldn't go to it
7105 mFakePolicy->assertNotifyAnrWasNotCalled();
7106
7107 mFocusedWindow->assertNoEvents();
7108 mUnfocusedWindow->assertNoEvents();
7109}
7110
7111/**
7112 * If a window is processing a motion event, and then a key event comes in, the key event should
7113 * not to to the focused window until the motion is processed.
7114 * If a different window becomes focused at this time, the key should go to that window instead.
7115 *
7116 * Warning!!!
7117 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7118 * and the injection timeout that we specify when injecting the key.
7119 * We must have the injection timeout (10ms) be smaller than
7120 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7121 *
7122 * If that value changes, this test should also change.
7123 */
7124TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7125 // Set a long ANR timeout to prevent it from triggering
7126 mFocusedWindow->setDispatchingTimeout(2s);
7127 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7128
7129 tapOnUnfocusedWindow();
7130 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7131 ASSERT_TRUE(downSequenceNum);
7132 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7133 ASSERT_TRUE(upSequenceNum);
7134 // Don't finish the events yet, and send a key
7135 // Injection will succeed because we will eventually give up and send the key to the focused
7136 // window even if motions are still being processed.
7137
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007138 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007139 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7140 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007141 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007142 // Key will not be sent to the window, yet, because the window is still processing events
7143 // and the key remains pending, waiting for the touch events to be processed
7144 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7145 ASSERT_FALSE(keySequenceNum);
7146
7147 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007148 mFocusedWindow->setFocusable(false);
7149 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007150 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007151 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007152
7153 // Focus events should precede the key events
7154 mUnfocusedWindow->consumeFocusEvent(true);
7155 mFocusedWindow->consumeFocusEvent(false);
7156
7157 // Finish the tap events, which should unblock dispatcher
7158 mUnfocusedWindow->finishEvent(*downSequenceNum);
7159 mUnfocusedWindow->finishEvent(*upSequenceNum);
7160
7161 // Now that all queues are cleared and no backlog in the connections, the key event
7162 // can finally go to the newly focused "mUnfocusedWindow".
7163 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7164 mFocusedWindow->assertNoEvents();
7165 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007166 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007167}
7168
7169// When the touch stream is split across 2 windows, and one of them does not respond,
7170// then ANR should be raised and the touch should be canceled for the unresponsive window.
7171// The other window should not be affected by that.
7172TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7173 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007174 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7175 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7176 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007177 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007178 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007179
7180 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007181 mDispatcher->notifyMotion(
7182 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7183 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007184
7185 const std::chrono::duration timeout =
7186 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007187 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007188
7189 mUnfocusedWindow->consumeMotionDown();
7190 mFocusedWindow->consumeMotionDown();
7191 // Focused window may or may not receive ACTION_MOVE
7192 // But it should definitely receive ACTION_CANCEL due to the ANR
7193 InputEvent* event;
7194 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7195 ASSERT_TRUE(moveOrCancelSequenceNum);
7196 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7197 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007198 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007199 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7200 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7201 mFocusedWindow->consumeMotionCancel();
7202 } else {
7203 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7204 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007205 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007206 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7207 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007208
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007209 mUnfocusedWindow->assertNoEvents();
7210 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007211 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007212}
7213
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007214/**
7215 * If we have no focused window, and a key comes in, we start the ANR timer.
7216 * The focused application should add a focused window before the timer runs out to prevent ANR.
7217 *
7218 * If the user touches another application during this time, the key should be dropped.
7219 * Next, if a new focused window comes in, without toggling the focused application,
7220 * then no ANR should occur.
7221 *
7222 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7223 * but in some cases the policy may not update the focused application.
7224 */
7225TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7226 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7227 std::make_shared<FakeApplicationHandle>();
7228 focusedApplication->setDispatchingTimeout(60ms);
7229 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7230 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7231 mFocusedWindow->setFocusable(false);
7232
7233 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7234 mFocusedWindow->consumeFocusEvent(false);
7235
7236 // Send a key. The ANR timer should start because there is no focused window.
7237 // 'focusedApplication' will get blamed if this timer completes.
7238 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007239 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007240 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7241 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
7242 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007243 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007244
7245 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7246 // then the injected touches won't cause the focused event to get dropped.
7247 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7248 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7249 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7250 // For this test, it means that the key would get delivered to the window once it becomes
7251 // focused.
7252 std::this_thread::sleep_for(10ms);
7253
7254 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007255 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7256 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7257 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007258
7259 // We do not consume the motion right away, because that would require dispatcher to first
7260 // process (== drop) the key event, and by that time, ANR will be raised.
7261 // Set the focused window first.
7262 mFocusedWindow->setFocusable(true);
7263 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7264 setFocusedWindow(mFocusedWindow);
7265 mFocusedWindow->consumeFocusEvent(true);
7266 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7267 // to another application. This could be a bug / behaviour in the policy.
7268
7269 mUnfocusedWindow->consumeMotionDown();
7270
7271 ASSERT_TRUE(mDispatcher->waitForIdle());
7272 // Should not ANR because we actually have a focused window. It was just added too slowly.
7273 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7274}
7275
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007276// These tests ensure we cannot send touch events to a window that's positioned behind a window
7277// that has feature NO_INPUT_CHANNEL.
7278// Layout:
7279// Top (closest to user)
7280// mNoInputWindow (above all windows)
7281// mBottomWindow
7282// Bottom (furthest from user)
7283class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7284 virtual void SetUp() override {
7285 InputDispatcherTest::SetUp();
7286
7287 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007288 mNoInputWindow =
7289 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7290 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007291 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007292 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007293 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7294 // It's perfectly valid for this window to not have an associated input channel
7295
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007296 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7297 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007298 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7299
7300 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7301 }
7302
7303protected:
7304 std::shared_ptr<FakeApplicationHandle> mApplication;
7305 sp<FakeWindowHandle> mNoInputWindow;
7306 sp<FakeWindowHandle> mBottomWindow;
7307};
7308
7309TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7310 PointF touchedPoint = {10, 10};
7311
Prabir Pradhan678438e2023-04-13 19:32:51 +00007312 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7313 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7314 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007315
7316 mNoInputWindow->assertNoEvents();
7317 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7318 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7319 // and therefore should prevent mBottomWindow from receiving touches
7320 mBottomWindow->assertNoEvents();
7321}
7322
7323/**
7324 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7325 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7326 */
7327TEST_F(InputDispatcherMultiWindowOcclusionTests,
7328 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007329 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7330 "Window with input channel and NO_INPUT_CHANNEL",
7331 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007332
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007333 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007334 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7335 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7336
7337 PointF touchedPoint = {10, 10};
7338
Prabir Pradhan678438e2023-04-13 19:32:51 +00007339 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7340 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7341 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007342
7343 mNoInputWindow->assertNoEvents();
7344 mBottomWindow->assertNoEvents();
7345}
7346
Vishnu Nair958da932020-08-21 17:12:37 -07007347class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7348protected:
7349 std::shared_ptr<FakeApplicationHandle> mApp;
7350 sp<FakeWindowHandle> mWindow;
7351 sp<FakeWindowHandle> mMirror;
7352
7353 virtual void SetUp() override {
7354 InputDispatcherTest::SetUp();
7355 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007356 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7357 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7358 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007359 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7360 mWindow->setFocusable(true);
7361 mMirror->setFocusable(true);
7362 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7363 }
7364};
7365
7366TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7367 // Request focus on a mirrored window
7368 setFocusedWindow(mMirror);
7369
7370 // window gets focused
7371 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007372 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7373 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007374 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7375}
7376
7377// A focused & mirrored window remains focused only if the window and its mirror are both
7378// focusable.
7379TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7380 setFocusedWindow(mMirror);
7381
7382 // window gets focused
7383 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7385 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007386 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007387 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7388 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007389 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7390
7391 mMirror->setFocusable(false);
7392 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7393
7394 // window loses focus since one of the windows associated with the token in not focusable
7395 mWindow->consumeFocusEvent(false);
7396
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007397 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7398 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007399 mWindow->assertNoEvents();
7400}
7401
7402// A focused & mirrored window remains focused until the window and its mirror both become
7403// invisible.
7404TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7405 setFocusedWindow(mMirror);
7406
7407 // window gets focused
7408 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007409 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7410 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007411 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007412 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7413 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007414 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7415
7416 mMirror->setVisible(false);
7417 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7418
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007419 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7420 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007421 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007422 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7423 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007424 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7425
7426 mWindow->setVisible(false);
7427 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7428
7429 // window loses focus only after all windows associated with the token become invisible.
7430 mWindow->consumeFocusEvent(false);
7431
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007432 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7433 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007434 mWindow->assertNoEvents();
7435}
7436
7437// A focused & mirrored window remains focused until both windows are removed.
7438TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7439 setFocusedWindow(mMirror);
7440
7441 // window gets focused
7442 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007443 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7444 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007445 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007446 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7447 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007448 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7449
7450 // single window is removed but the window token remains focused
7451 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7452
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007453 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7454 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007455 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007456 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7457 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007458 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7459
7460 // Both windows are removed
7461 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7462 mWindow->consumeFocusEvent(false);
7463
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007464 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7465 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007466 mWindow->assertNoEvents();
7467}
7468
7469// Focus request can be pending until one window becomes visible.
7470TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7471 // Request focus on an invisible mirror.
7472 mWindow->setVisible(false);
7473 mMirror->setVisible(false);
7474 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7475 setFocusedWindow(mMirror);
7476
7477 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007478 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007479 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7480 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007481
7482 mMirror->setVisible(true);
7483 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7484
7485 // window gets focused
7486 mWindow->consumeFocusEvent(true);
7487 // window gets the pending key event
7488 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7489}
Prabir Pradhan99987712020-11-10 18:43:05 -08007490
7491class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7492protected:
7493 std::shared_ptr<FakeApplicationHandle> mApp;
7494 sp<FakeWindowHandle> mWindow;
7495 sp<FakeWindowHandle> mSecondWindow;
7496
7497 void SetUp() override {
7498 InputDispatcherTest::SetUp();
7499 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007500 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007501 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007502 mSecondWindow =
7503 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007504 mSecondWindow->setFocusable(true);
7505
7506 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7507 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7508
7509 setFocusedWindow(mWindow);
7510 mWindow->consumeFocusEvent(true);
7511 }
7512
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007513 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007514 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007515 }
7516
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007517 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7518 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007519 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007520 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7521 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007522 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007523 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007524 }
7525};
7526
7527TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7528 // Ensure that capture cannot be obtained for unfocused windows.
7529 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7530 mFakePolicy->assertSetPointerCaptureNotCalled();
7531 mSecondWindow->assertNoEvents();
7532
7533 // Ensure that capture can be enabled from the focus window.
7534 requestAndVerifyPointerCapture(mWindow, true);
7535
7536 // Ensure that capture cannot be disabled from a window that does not have capture.
7537 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7538 mFakePolicy->assertSetPointerCaptureNotCalled();
7539
7540 // Ensure that capture can be disabled from the window with capture.
7541 requestAndVerifyPointerCapture(mWindow, false);
7542}
7543
7544TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007545 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007546
7547 setFocusedWindow(mSecondWindow);
7548
7549 // Ensure that the capture disabled event was sent first.
7550 mWindow->consumeCaptureEvent(false);
7551 mWindow->consumeFocusEvent(false);
7552 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007553 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007554
7555 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007556 notifyPointerCaptureChanged({});
7557 notifyPointerCaptureChanged(request);
7558 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007559 mWindow->assertNoEvents();
7560 mSecondWindow->assertNoEvents();
7561 mFakePolicy->assertSetPointerCaptureNotCalled();
7562}
7563
7564TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007565 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007566
7567 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007568 notifyPointerCaptureChanged({});
7569 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007570
7571 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007572 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007573 mWindow->consumeCaptureEvent(false);
7574 mWindow->assertNoEvents();
7575}
7576
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007577TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7578 requestAndVerifyPointerCapture(mWindow, true);
7579
7580 // The first window loses focus.
7581 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007582 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007583 mWindow->consumeCaptureEvent(false);
7584
7585 // Request Pointer Capture from the second window before the notification from InputReader
7586 // arrives.
7587 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007588 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007589
7590 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007591 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007592
7593 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007594 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007595
7596 mSecondWindow->consumeFocusEvent(true);
7597 mSecondWindow->consumeCaptureEvent(true);
7598}
7599
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007600TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7601 // App repeatedly enables and disables capture.
7602 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7603 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7604 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7605 mFakePolicy->assertSetPointerCaptureCalled(false);
7606 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7607 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7608
7609 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7610 // first request is now stale, this should do nothing.
7611 notifyPointerCaptureChanged(firstRequest);
7612 mWindow->assertNoEvents();
7613
7614 // InputReader notifies that the second request was enabled.
7615 notifyPointerCaptureChanged(secondRequest);
7616 mWindow->consumeCaptureEvent(true);
7617}
7618
Prabir Pradhan7092e262022-05-03 16:51:09 +00007619TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7620 requestAndVerifyPointerCapture(mWindow, true);
7621
7622 // App toggles pointer capture off and on.
7623 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7624 mFakePolicy->assertSetPointerCaptureCalled(false);
7625
7626 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7627 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7628
7629 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7630 // preceding "disable" request.
7631 notifyPointerCaptureChanged(enableRequest);
7632
7633 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7634 // any notifications.
7635 mWindow->assertNoEvents();
7636}
7637
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007638class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7639protected:
7640 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007641
7642 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7643 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7644
7645 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7646 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7647
7648 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7649 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7650 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7651 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7652 MAXIMUM_OBSCURING_OPACITY);
7653
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007654 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007655 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007656 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007657
7658 sp<FakeWindowHandle> mTouchWindow;
7659
7660 virtual void SetUp() override {
7661 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007662 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007663 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7664 }
7665
7666 virtual void TearDown() override {
7667 InputDispatcherTest::TearDown();
7668 mTouchWindow.clear();
7669 }
7670
chaviw3277faf2021-05-19 16:45:23 -05007671 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
7672 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007673 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007674 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007675 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007676 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007677 return window;
7678 }
7679
7680 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
7681 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7682 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007683 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007684 // Generate an arbitrary PID based on the UID
7685 window->setOwnerInfo(1777 + (uid % 10000), uid);
7686 return window;
7687 }
7688
7689 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007690 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7691 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7692 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007693 }
7694};
7695
7696TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007697 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007698 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007699 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007700
7701 touch();
7702
7703 mTouchWindow->assertNoEvents();
7704}
7705
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007706TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007707 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7708 const sp<FakeWindowHandle>& w =
7709 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7710 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7711
7712 touch();
7713
7714 mTouchWindow->assertNoEvents();
7715}
7716
7717TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007718 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7719 const sp<FakeWindowHandle>& w =
7720 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7721 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7722
7723 touch();
7724
7725 w->assertNoEvents();
7726}
7727
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007728TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007729 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7730 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007731
7732 touch();
7733
7734 mTouchWindow->consumeAnyMotionDown();
7735}
7736
7737TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007738 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007739 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007740 w->setFrame(Rect(0, 0, 50, 50));
7741 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007742
7743 touch({PointF{100, 100}});
7744
7745 mTouchWindow->consumeAnyMotionDown();
7746}
7747
7748TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007749 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007750 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007751 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7752
7753 touch();
7754
7755 mTouchWindow->consumeAnyMotionDown();
7756}
7757
7758TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7759 const sp<FakeWindowHandle>& w =
7760 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7761 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007762
7763 touch();
7764
7765 mTouchWindow->consumeAnyMotionDown();
7766}
7767
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007768TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7769 const sp<FakeWindowHandle>& w =
7770 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7771 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7772
7773 touch();
7774
7775 w->assertNoEvents();
7776}
7777
7778/**
7779 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
7780 * inside) while letting them pass-through. Note that even though touch passes through the occluding
7781 * window, the occluding window will still receive ACTION_OUTSIDE event.
7782 */
7783TEST_F(InputDispatcherUntrustedTouchesTest,
7784 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
7785 const sp<FakeWindowHandle>& w =
7786 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007787 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007788 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7789
7790 touch();
7791
7792 w->consumeMotionOutside();
7793}
7794
7795TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
7796 const sp<FakeWindowHandle>& w =
7797 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007798 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007799 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7800
7801 touch();
7802
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007803 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007804}
7805
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007806TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007807 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007808 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7809 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007810 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7811
7812 touch();
7813
7814 mTouchWindow->consumeAnyMotionDown();
7815}
7816
7817TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
7818 const sp<FakeWindowHandle>& w =
7819 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7820 MAXIMUM_OBSCURING_OPACITY);
7821 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007822
7823 touch();
7824
7825 mTouchWindow->consumeAnyMotionDown();
7826}
7827
7828TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007829 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007830 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7831 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007832 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7833
7834 touch();
7835
7836 mTouchWindow->assertNoEvents();
7837}
7838
7839TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
7840 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
7841 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007842 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7843 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007844 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007845 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7846 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007847 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7848
7849 touch();
7850
7851 mTouchWindow->assertNoEvents();
7852}
7853
7854TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
7855 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
7856 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007857 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7858 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007859 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007860 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7861 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007862 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7863
7864 touch();
7865
7866 mTouchWindow->consumeAnyMotionDown();
7867}
7868
7869TEST_F(InputDispatcherUntrustedTouchesTest,
7870 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
7871 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007872 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7873 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007874 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007875 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7876 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007877 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
7878
7879 touch();
7880
7881 mTouchWindow->consumeAnyMotionDown();
7882}
7883
7884TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
7885 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007886 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7887 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007888 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007889 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7890 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007891 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007892
7893 touch();
7894
7895 mTouchWindow->assertNoEvents();
7896}
7897
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007898TEST_F(InputDispatcherUntrustedTouchesTest,
7899 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
7900 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007901 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7902 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007903 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007904 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7905 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007906 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7907
7908 touch();
7909
7910 mTouchWindow->assertNoEvents();
7911}
7912
7913TEST_F(InputDispatcherUntrustedTouchesTest,
7914 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
7915 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007916 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7917 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007918 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007919 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7920 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007921 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7922
7923 touch();
7924
7925 mTouchWindow->consumeAnyMotionDown();
7926}
7927
7928TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
7929 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007930 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7931 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007932 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7933
7934 touch();
7935
7936 mTouchWindow->consumeAnyMotionDown();
7937}
7938
7939TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
7940 const sp<FakeWindowHandle>& w =
7941 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
7942 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7943
7944 touch();
7945
7946 mTouchWindow->consumeAnyMotionDown();
7947}
7948
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00007949TEST_F(InputDispatcherUntrustedTouchesTest,
7950 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
7951 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
7952 const sp<FakeWindowHandle>& w =
7953 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
7954 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7955
7956 touch();
7957
7958 mTouchWindow->assertNoEvents();
7959}
7960
7961TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
7962 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
7963 const sp<FakeWindowHandle>& w =
7964 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
7965 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7966
7967 touch();
7968
7969 mTouchWindow->consumeAnyMotionDown();
7970}
7971
7972TEST_F(InputDispatcherUntrustedTouchesTest,
7973 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
7974 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
7975 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007976 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7977 OPACITY_ABOVE_THRESHOLD);
7978 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7979
7980 touch();
7981
7982 mTouchWindow->consumeAnyMotionDown();
7983}
7984
7985TEST_F(InputDispatcherUntrustedTouchesTest,
7986 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
7987 const sp<FakeWindowHandle>& w1 =
7988 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
7989 OPACITY_BELOW_THRESHOLD);
7990 const sp<FakeWindowHandle>& w2 =
7991 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7992 OPACITY_BELOW_THRESHOLD);
7993 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7994
7995 touch();
7996
7997 mTouchWindow->assertNoEvents();
7998}
7999
8000/**
8001 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8002 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8003 * (which alone would result in allowing touches) does not affect the blocking behavior.
8004 */
8005TEST_F(InputDispatcherUntrustedTouchesTest,
8006 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8007 const sp<FakeWindowHandle>& wB =
8008 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8009 OPACITY_BELOW_THRESHOLD);
8010 const sp<FakeWindowHandle>& wC =
8011 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8012 OPACITY_BELOW_THRESHOLD);
8013 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8014
8015 touch();
8016
8017 mTouchWindow->assertNoEvents();
8018}
8019
8020/**
8021 * This test is testing that a window from a different UID but with same application token doesn't
8022 * block the touch. Apps can share the application token for close UI collaboration for example.
8023 */
8024TEST_F(InputDispatcherUntrustedTouchesTest,
8025 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8026 const sp<FakeWindowHandle>& w =
8027 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8028 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008029 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8030
8031 touch();
8032
8033 mTouchWindow->consumeAnyMotionDown();
8034}
8035
arthurhungb89ccb02020-12-30 16:19:01 +08008036class InputDispatcherDragTests : public InputDispatcherTest {
8037protected:
8038 std::shared_ptr<FakeApplicationHandle> mApp;
8039 sp<FakeWindowHandle> mWindow;
8040 sp<FakeWindowHandle> mSecondWindow;
8041 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008042 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008043 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8044 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008045
8046 void SetUp() override {
8047 InputDispatcherTest::SetUp();
8048 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008049 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008050 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008051
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008052 mSecondWindow =
8053 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008054 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008055
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008056 mSpyWindow =
8057 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008058 mSpyWindow->setSpy(true);
8059 mSpyWindow->setTrustedOverlay(true);
8060 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8061
arthurhungb89ccb02020-12-30 16:19:01 +08008062 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008063 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008064 }
8065
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008066 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8067 switch (fromSource) {
8068 case AINPUT_SOURCE_TOUCHSCREEN:
8069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8070 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8071 ADISPLAY_ID_DEFAULT, {50, 50}))
8072 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8073 break;
8074 case AINPUT_SOURCE_STYLUS:
8075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8076 injectMotionEvent(
8077 mDispatcher,
8078 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8079 AINPUT_SOURCE_STYLUS)
8080 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008081 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008082 .x(50)
8083 .y(50))
8084 .build()));
8085 break;
8086 case AINPUT_SOURCE_MOUSE:
8087 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8088 injectMotionEvent(
8089 mDispatcher,
8090 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8091 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8092 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008093 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008094 .x(50)
8095 .y(50))
8096 .build()));
8097 break;
8098 default:
8099 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8100 }
arthurhungb89ccb02020-12-30 16:19:01 +08008101
8102 // Window should receive motion event.
8103 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008104 // Spy window should also receive motion event
8105 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008106 }
8107
8108 // Start performing drag, we will create a drag window and transfer touch to it.
8109 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8110 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008111 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008112 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008113 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008114 }
arthurhungb89ccb02020-12-30 16:19:01 +08008115
8116 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008117 mDragWindow =
8118 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008119 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08008120 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008121 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008122
8123 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008124 bool transferred =
8125 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008126 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008127 if (transferred) {
8128 mWindow->consumeMotionCancel();
8129 mDragWindow->consumeMotionDown();
8130 }
8131 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008132 }
8133};
8134
8135TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008136 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008137
8138 // Move on window.
8139 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8140 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8141 ADISPLAY_ID_DEFAULT, {50, 50}))
8142 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8143 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8144 mWindow->consumeDragEvent(false, 50, 50);
8145 mSecondWindow->assertNoEvents();
8146
8147 // Move to another window.
8148 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8149 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8150 ADISPLAY_ID_DEFAULT, {150, 50}))
8151 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8152 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8153 mWindow->consumeDragEvent(true, 150, 50);
8154 mSecondWindow->consumeDragEvent(false, 50, 50);
8155
8156 // Move back to original window.
8157 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8158 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8159 ADISPLAY_ID_DEFAULT, {50, 50}))
8160 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8161 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8162 mWindow->consumeDragEvent(false, 50, 50);
8163 mSecondWindow->consumeDragEvent(true, -50, 50);
8164
8165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8166 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8167 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8168 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8169 mWindow->assertNoEvents();
8170 mSecondWindow->assertNoEvents();
8171}
8172
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008173TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008174 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008175
8176 // No cancel event after drag start
8177 mSpyWindow->assertNoEvents();
8178
8179 const MotionEvent secondFingerDownEvent =
8180 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8181 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008182 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8183 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008184 .build();
8185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8186 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8187 InputEventInjectionSync::WAIT_FOR_RESULT))
8188 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8189
8190 // Receives cancel for first pointer after next pointer down
8191 mSpyWindow->consumeMotionCancel();
8192 mSpyWindow->consumeMotionDown();
8193
8194 mSpyWindow->assertNoEvents();
8195}
8196
arthurhungf452d0b2021-01-06 00:19:52 +08008197TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008198 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008199
8200 // Move on window.
8201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8202 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8203 ADISPLAY_ID_DEFAULT, {50, 50}))
8204 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8205 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8206 mWindow->consumeDragEvent(false, 50, 50);
8207 mSecondWindow->assertNoEvents();
8208
8209 // Move to another window.
8210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8211 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8212 ADISPLAY_ID_DEFAULT, {150, 50}))
8213 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8214 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8215 mWindow->consumeDragEvent(true, 150, 50);
8216 mSecondWindow->consumeDragEvent(false, 50, 50);
8217
8218 // drop to another window.
8219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8220 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8221 {150, 50}))
8222 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8223 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8224 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8225 mWindow->assertNoEvents();
8226 mSecondWindow->assertNoEvents();
8227}
8228
arthurhung6d4bed92021-03-17 11:59:33 +08008229TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008230 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008231
8232 // Move on window and keep button pressed.
8233 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8234 injectMotionEvent(mDispatcher,
8235 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8236 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008237 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008238 .build()))
8239 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8240 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8241 mWindow->consumeDragEvent(false, 50, 50);
8242 mSecondWindow->assertNoEvents();
8243
8244 // Move to another window and release button, expect to drop item.
8245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8246 injectMotionEvent(mDispatcher,
8247 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8248 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008249 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008250 .build()))
8251 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8252 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8253 mWindow->assertNoEvents();
8254 mSecondWindow->assertNoEvents();
8255 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8256
8257 // nothing to the window.
8258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8259 injectMotionEvent(mDispatcher,
8260 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8261 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008262 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008263 .build()))
8264 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8265 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8266 mWindow->assertNoEvents();
8267 mSecondWindow->assertNoEvents();
8268}
8269
Arthur Hung54745652022-04-20 07:17:41 +00008270TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008271 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008272
8273 // Set second window invisible.
8274 mSecondWindow->setVisible(false);
8275 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8276
8277 // Move on window.
8278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8279 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8280 ADISPLAY_ID_DEFAULT, {50, 50}))
8281 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8282 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8283 mWindow->consumeDragEvent(false, 50, 50);
8284 mSecondWindow->assertNoEvents();
8285
8286 // Move to another window.
8287 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8288 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8289 ADISPLAY_ID_DEFAULT, {150, 50}))
8290 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8291 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8292 mWindow->consumeDragEvent(true, 150, 50);
8293 mSecondWindow->assertNoEvents();
8294
8295 // drop to another window.
8296 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8297 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8298 {150, 50}))
8299 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8300 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8301 mFakePolicy->assertDropTargetEquals(nullptr);
8302 mWindow->assertNoEvents();
8303 mSecondWindow->assertNoEvents();
8304}
8305
Arthur Hung54745652022-04-20 07:17:41 +00008306TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008307 // Ensure window could track pointerIds if it didn't support split touch.
8308 mWindow->setPreventSplitting(true);
8309
Arthur Hung54745652022-04-20 07:17:41 +00008310 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8311 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8312 {50, 50}))
8313 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8314 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8315
8316 const MotionEvent secondFingerDownEvent =
8317 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8318 .displayId(ADISPLAY_ID_DEFAULT)
8319 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008320 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8321 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008322 .build();
8323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8324 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8325 InputEventInjectionSync::WAIT_FOR_RESULT))
8326 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008327 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008328
8329 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008330 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008331}
8332
8333TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8334 // First down on second window.
8335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8336 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8337 {150, 50}))
8338 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8339
8340 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8341
8342 // Second down on first window.
8343 const MotionEvent secondFingerDownEvent =
8344 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8345 .displayId(ADISPLAY_ID_DEFAULT)
8346 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008347 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8348 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008349 .build();
8350 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8351 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8352 InputEventInjectionSync::WAIT_FOR_RESULT))
8353 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8354 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8355
8356 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008357 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008358
8359 // Move on window.
8360 const MotionEvent secondFingerMoveEvent =
8361 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8362 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008363 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8364 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008365 .build();
8366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8367 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8368 InputEventInjectionSync::WAIT_FOR_RESULT));
8369 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8370 mWindow->consumeDragEvent(false, 50, 50);
8371 mSecondWindow->consumeMotionMove();
8372
8373 // Release the drag pointer should perform drop.
8374 const MotionEvent secondFingerUpEvent =
8375 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8376 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008377 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8378 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008379 .build();
8380 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8381 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8382 InputEventInjectionSync::WAIT_FOR_RESULT));
8383 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8384 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
8385 mWindow->assertNoEvents();
8386 mSecondWindow->consumeMotionMove();
8387}
8388
Arthur Hung3915c1f2022-05-31 07:17:17 +00008389TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008390 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008391
8392 // Update window of second display.
8393 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008394 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008395 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8396
8397 // Let second display has a touch state.
8398 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8399 injectMotionEvent(mDispatcher,
8400 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8401 AINPUT_SOURCE_TOUCHSCREEN)
8402 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008403 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008404 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008405 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008406 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008407 // Update window again.
8408 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8409
8410 // Move on window.
8411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8412 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8413 ADISPLAY_ID_DEFAULT, {50, 50}))
8414 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8415 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8416 mWindow->consumeDragEvent(false, 50, 50);
8417 mSecondWindow->assertNoEvents();
8418
8419 // Move to another window.
8420 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8421 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8422 ADISPLAY_ID_DEFAULT, {150, 50}))
8423 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8424 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8425 mWindow->consumeDragEvent(true, 150, 50);
8426 mSecondWindow->consumeDragEvent(false, 50, 50);
8427
8428 // drop to another window.
8429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8430 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8431 {150, 50}))
8432 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8433 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8434 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8435 mWindow->assertNoEvents();
8436 mSecondWindow->assertNoEvents();
8437}
8438
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008439TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8440 startDrag(true, AINPUT_SOURCE_MOUSE);
8441 // Move on window.
8442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8443 injectMotionEvent(mDispatcher,
8444 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8445 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8446 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008447 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008448 .x(50)
8449 .y(50))
8450 .build()))
8451 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8452 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8453 mWindow->consumeDragEvent(false, 50, 50);
8454 mSecondWindow->assertNoEvents();
8455
8456 // Move to another window.
8457 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8458 injectMotionEvent(mDispatcher,
8459 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8460 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8461 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008462 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008463 .x(150)
8464 .y(50))
8465 .build()))
8466 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8467 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8468 mWindow->consumeDragEvent(true, 150, 50);
8469 mSecondWindow->consumeDragEvent(false, 50, 50);
8470
8471 // drop to another window.
8472 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8473 injectMotionEvent(mDispatcher,
8474 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8475 .buttonState(0)
8476 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008477 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008478 .x(150)
8479 .y(50))
8480 .build()))
8481 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8482 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8483 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8484 mWindow->assertNoEvents();
8485 mSecondWindow->assertNoEvents();
8486}
8487
Vishnu Nair062a8672021-09-03 16:07:44 -07008488class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8489
8490TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8491 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008492 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8493 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008494 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008495 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8496 window->setFocusable(true);
8497 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8498 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008499 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008500
8501 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008502 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008503 window->assertNoEvents();
8504
Prabir Pradhan678438e2023-04-13 19:32:51 +00008505 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8506 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008507 window->assertNoEvents();
8508
8509 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008510 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008511 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8512
Prabir Pradhan678438e2023-04-13 19:32:51 +00008513 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008514 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8515
Prabir Pradhan678438e2023-04-13 19:32:51 +00008516 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8517 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008518 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8519 window->assertNoEvents();
8520}
8521
8522TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8523 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8524 std::make_shared<FakeApplicationHandle>();
8525 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008526 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8527 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008528 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8529 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008530 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008531 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008532 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8533 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008534 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008535 window->setOwnerInfo(222, 222);
8536 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8537 window->setFocusable(true);
8538 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8539 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008540 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008541
8542 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008543 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008544 window->assertNoEvents();
8545
Prabir Pradhan678438e2023-04-13 19:32:51 +00008546 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8547 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008548 window->assertNoEvents();
8549
8550 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008551 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008552 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8553
Prabir Pradhan678438e2023-04-13 19:32:51 +00008554 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008555 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8556
Prabir Pradhan678438e2023-04-13 19:32:51 +00008557 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8558 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008559 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8560 window->assertNoEvents();
8561}
8562
8563TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8564 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8565 std::make_shared<FakeApplicationHandle>();
8566 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008567 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8568 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008569 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8570 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008571 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008572 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008573 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8574 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008575 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008576 window->setOwnerInfo(222, 222);
8577 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8578 window->setFocusable(true);
8579 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8580 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008581 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008582
8583 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008584 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008585 window->assertNoEvents();
8586
Prabir Pradhan678438e2023-04-13 19:32:51 +00008587 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8588 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008589 window->assertNoEvents();
8590
8591 // When the window is no longer obscured because it went on top, it should get input
8592 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8593
Prabir Pradhan678438e2023-04-13 19:32:51 +00008594 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008595 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8596
Prabir Pradhan678438e2023-04-13 19:32:51 +00008597 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8598 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008599 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8600 window->assertNoEvents();
8601}
8602
Antonio Kantekf16f2832021-09-28 04:39:20 +00008603class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8604protected:
8605 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008606 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008607 sp<FakeWindowHandle> mWindow;
8608 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008609 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008610
8611 void SetUp() override {
8612 InputDispatcherTest::SetUp();
8613
8614 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008615 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008616 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008617 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008618 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008619 mSecondWindow =
8620 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008621 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008622 mThirdWindow =
8623 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8624 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8625 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008626
8627 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008628 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8629 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8630 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008631 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008632
Antonio Kantek15beb512022-06-13 22:35:41 +00008633 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008634 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008635 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008636 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8637 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008638 mThirdWindow->assertNoEvents();
8639 }
8640
8641 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8642 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008643 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008644 SECOND_DISPLAY_ID)) {
8645 mWindow->assertNoEvents();
8646 mSecondWindow->assertNoEvents();
8647 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008648 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008649 }
8650
Antonio Kantek15beb512022-06-13 22:35:41 +00008651 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid,
8652 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008653 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8654 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008655 mWindow->consumeTouchModeEvent(inTouchMode);
8656 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008657 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008658 }
8659};
8660
Antonio Kantek26defcf2022-02-08 01:12:27 +00008661TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008662 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008663 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8664 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008665 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008666}
8667
Antonio Kantek26defcf2022-02-08 01:12:27 +00008668TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8669 const WindowInfo& windowInfo = *mWindow->getInfo();
8670 int32_t ownerPid = windowInfo.ownerPid;
8671 int32_t ownerUid = windowInfo.ownerUid;
8672 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
8673 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008674 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008675 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008676 mWindow->assertNoEvents();
8677 mSecondWindow->assertNoEvents();
8678}
8679
8680TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8681 const WindowInfo& windowInfo = *mWindow->getInfo();
8682 int32_t ownerPid = windowInfo.ownerPid;
8683 int32_t ownerUid = windowInfo.ownerUid;
8684 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
Antonio Kantek15beb512022-06-13 22:35:41 +00008685 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008686 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008687}
8688
Antonio Kantekf16f2832021-09-28 04:39:20 +00008689TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008690 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008691 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8692 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008693 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008694 mWindow->assertNoEvents();
8695 mSecondWindow->assertNoEvents();
8696}
8697
Antonio Kantek15beb512022-06-13 22:35:41 +00008698TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8699 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8700 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8701 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008702 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008703 mWindow->assertNoEvents();
8704 mSecondWindow->assertNoEvents();
8705 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8706}
8707
Antonio Kantek48710e42022-03-24 14:19:30 -07008708TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8709 // Interact with the window first.
8710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8711 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8712 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8713
8714 // Then remove focus.
8715 mWindow->setFocusable(false);
8716 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8717
8718 // Assert that caller can switch touch mode by owning one of the last interacted window.
8719 const WindowInfo& windowInfo = *mWindow->getInfo();
8720 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8721 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008722 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008723}
8724
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008725class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8726public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008727 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008728 std::shared_ptr<FakeApplicationHandle> application =
8729 std::make_shared<FakeApplicationHandle>();
8730 std::string name = "Fake Spy ";
8731 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008732 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8733 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008734 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008735 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008736 return spy;
8737 }
8738
8739 sp<FakeWindowHandle> createForeground() {
8740 std::shared_ptr<FakeApplicationHandle> application =
8741 std::make_shared<FakeApplicationHandle>();
8742 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008743 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8744 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008745 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008746 return window;
8747 }
8748
8749private:
8750 int mSpyCount{0};
8751};
8752
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008753using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008754/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008755 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8756 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008757TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8758 ScopedSilentDeath _silentDeath;
8759
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008760 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008761 spy->setTrustedOverlay(false);
8762 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8763 ".* not a trusted overlay");
8764}
8765
8766/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008767 * Input injection into a display with a spy window but no foreground windows should succeed.
8768 */
8769TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008770 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008771 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
8772
8773 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8774 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8775 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8776 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8777}
8778
8779/**
8780 * Verify the order in which different input windows receive events. The touched foreground window
8781 * (if there is one) should always receive the event first. When there are multiple spy windows, the
8782 * spy windows will receive the event according to their Z-order, where the top-most spy window will
8783 * receive events before ones belows it.
8784 *
8785 * Here, we set up a scenario with four windows in the following Z order from the top:
8786 * spy1, spy2, window, spy3.
8787 * We then inject an event and verify that the foreground "window" receives it first, followed by
8788 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
8789 * window.
8790 */
8791TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
8792 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008793 auto spy1 = createSpy();
8794 auto spy2 = createSpy();
8795 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008796 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
8797 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
8798 const size_t numChannels = channels.size();
8799
Michael Wright8e9a8562022-02-09 13:44:29 +00008800 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008801 if (!epollFd.ok()) {
8802 FAIL() << "Failed to create epoll fd";
8803 }
8804
8805 for (size_t i = 0; i < numChannels; i++) {
8806 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
8807 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
8808 FAIL() << "Failed to add fd to epoll";
8809 }
8810 }
8811
8812 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8813 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8814 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8815
8816 std::vector<size_t> eventOrder;
8817 std::vector<struct epoll_event> events(numChannels);
8818 for (;;) {
8819 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
8820 (100ms).count());
8821 if (nFds < 0) {
8822 FAIL() << "Failed to call epoll_wait";
8823 }
8824 if (nFds == 0) {
8825 break; // epoll_wait timed out
8826 }
8827 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07008828 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07008829 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008830 channels[i]->consumeMotionDown();
8831 }
8832 }
8833
8834 // Verify the order in which the events were received.
8835 EXPECT_EQ(3u, eventOrder.size());
8836 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
8837 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
8838 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
8839}
8840
8841/**
8842 * A spy window using the NOT_TOUCHABLE flag does not receive events.
8843 */
8844TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
8845 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008846 auto spy = createSpy();
8847 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008848 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8849
8850 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8851 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8852 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8853 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8854 spy->assertNoEvents();
8855}
8856
8857/**
8858 * A spy window will only receive gestures that originate within its touchable region. Gestures that
8859 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
8860 * to the window.
8861 */
8862TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
8863 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008864 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008865 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
8866 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8867
8868 // Inject an event outside the spy window's touchable region.
8869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8870 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8871 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8872 window->consumeMotionDown();
8873 spy->assertNoEvents();
8874 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8875 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8876 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8877 window->consumeMotionUp();
8878 spy->assertNoEvents();
8879
8880 // Inject an event inside the spy window's touchable region.
8881 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8882 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8883 {5, 10}))
8884 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8885 window->consumeMotionDown();
8886 spy->consumeMotionDown();
8887}
8888
8889/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008890 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008891 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008892 */
8893TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
8894 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008895 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008896 auto spy = createSpy();
8897 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008898 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008899 spy->setFrame(Rect{0, 0, 20, 20});
8900 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8901
8902 // Inject an event outside the spy window's frame and touchable region.
8903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008904 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8905 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008906 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8907 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008908 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008909}
8910
8911/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008912 * Even when a spy window spans over multiple foreground windows, the spy should receive all
8913 * pointers that are down within its bounds.
8914 */
8915TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
8916 auto windowLeft = createForeground();
8917 windowLeft->setFrame({0, 0, 100, 200});
8918 auto windowRight = createForeground();
8919 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008920 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008921 spy->setFrame({0, 0, 200, 200});
8922 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
8923
8924 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8925 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8926 {50, 50}))
8927 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8928 windowLeft->consumeMotionDown();
8929 spy->consumeMotionDown();
8930
8931 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008932 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008933 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008934 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8935 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008936 .build();
8937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8938 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8939 InputEventInjectionSync::WAIT_FOR_RESULT))
8940 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8941 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00008942 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008943}
8944
8945/**
8946 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
8947 * the spy should receive the second pointer with ACTION_DOWN.
8948 */
8949TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
8950 auto window = createForeground();
8951 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008952 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008953 spyRight->setFrame({100, 0, 200, 200});
8954 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
8955
8956 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8957 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8958 {50, 50}))
8959 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8960 window->consumeMotionDown();
8961 spyRight->assertNoEvents();
8962
8963 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008964 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008965 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008966 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8967 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008968 .build();
8969 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8970 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8971 InputEventInjectionSync::WAIT_FOR_RESULT))
8972 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008973 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008974 spyRight->consumeMotionDown();
8975}
8976
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008977/**
8978 * The spy window should not be able to affect whether or not touches are split. Only the foreground
8979 * windows should be allowed to control split touch.
8980 */
8981TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008982 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008983 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008984 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008985 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008986
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008987 auto window = createForeground();
8988 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008989
8990 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8991
8992 // First finger down, no window touched.
8993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8994 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8995 {100, 200}))
8996 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8997 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8998 window->assertNoEvents();
8999
9000 // Second finger down on window, the window should receive touch down.
9001 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009002 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009003 .displayId(ADISPLAY_ID_DEFAULT)
9004 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009005 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9006 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009007 .build();
9008 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9009 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9010 InputEventInjectionSync::WAIT_FOR_RESULT))
9011 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9012
9013 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009014 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009015}
9016
9017/**
9018 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9019 * do not receive key events.
9020 */
9021TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009022 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009023 spy->setFocusable(false);
9024
9025 auto window = createForeground();
9026 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9027 setFocusedWindow(window);
9028 window->consumeFocusEvent(true);
9029
9030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
9031 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9032 window->consumeKeyDown(ADISPLAY_ID_NONE);
9033
9034 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
9035 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9036 window->consumeKeyUp(ADISPLAY_ID_NONE);
9037
9038 spy->assertNoEvents();
9039}
9040
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009041using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9042
9043/**
9044 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9045 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9046 */
9047TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9048 auto window = createForeground();
9049 auto spy1 = createSpy();
9050 auto spy2 = createSpy();
9051 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
9052
9053 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9054 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9055 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9056 window->consumeMotionDown();
9057 spy1->consumeMotionDown();
9058 spy2->consumeMotionDown();
9059
9060 // Pilfer pointers from the second spy window.
9061 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9062 spy2->assertNoEvents();
9063 spy1->consumeMotionCancel();
9064 window->consumeMotionCancel();
9065
9066 // The rest of the gesture should only be sent to the second spy window.
9067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9068 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9069 ADISPLAY_ID_DEFAULT))
9070 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9071 spy2->consumeMotionMove();
9072 spy1->assertNoEvents();
9073 window->assertNoEvents();
9074}
9075
9076/**
9077 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9078 * in the middle of the gesture.
9079 */
9080TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9081 auto window = createForeground();
9082 auto spy = createSpy();
9083 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9084
9085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9086 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9087 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9088 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9089 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9090
9091 window->releaseChannel();
9092
9093 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9094
9095 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9096 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9097 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9098 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9099}
9100
9101/**
9102 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9103 * the spy, but not to any other windows.
9104 */
9105TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9106 auto spy = createSpy();
9107 auto window = createForeground();
9108
9109 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9110
9111 // First finger down on the window and the spy.
9112 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9113 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9114 {100, 200}))
9115 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9116 spy->consumeMotionDown();
9117 window->consumeMotionDown();
9118
9119 // Spy window pilfers the pointers.
9120 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9121 window->consumeMotionCancel();
9122
9123 // Second finger down on the window and spy, but the window should not receive the pointer down.
9124 const MotionEvent secondFingerDownEvent =
9125 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9126 .displayId(ADISPLAY_ID_DEFAULT)
9127 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009128 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9129 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009130 .build();
9131 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9132 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9133 InputEventInjectionSync::WAIT_FOR_RESULT))
9134 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9135
Harry Cutts33476232023-01-30 19:57:29 +00009136 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009137
9138 // Third finger goes down outside all windows, so injection should fail.
9139 const MotionEvent thirdFingerDownEvent =
9140 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9141 .displayId(ADISPLAY_ID_DEFAULT)
9142 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009143 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9144 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9145 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009146 .build();
9147 ASSERT_EQ(InputEventInjectionResult::FAILED,
9148 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9149 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009150 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009151
9152 spy->assertNoEvents();
9153 window->assertNoEvents();
9154}
9155
9156/**
9157 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9158 */
9159TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9160 auto spy = createSpy();
9161 spy->setFrame(Rect(0, 0, 100, 100));
9162 auto window = createForeground();
9163 window->setFrame(Rect(0, 0, 200, 200));
9164
9165 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9166
9167 // First finger down on the window only
9168 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9169 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9170 {150, 150}))
9171 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9172 window->consumeMotionDown();
9173
9174 // Second finger down on the spy and window
9175 const MotionEvent secondFingerDownEvent =
9176 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9177 .displayId(ADISPLAY_ID_DEFAULT)
9178 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009179 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9180 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009181 .build();
9182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9183 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9184 InputEventInjectionSync::WAIT_FOR_RESULT))
9185 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9186 spy->consumeMotionDown();
9187 window->consumeMotionPointerDown(1);
9188
9189 // Third finger down on the spy and window
9190 const MotionEvent thirdFingerDownEvent =
9191 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9192 .displayId(ADISPLAY_ID_DEFAULT)
9193 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009194 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9195 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9196 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009197 .build();
9198 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9199 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9200 InputEventInjectionSync::WAIT_FOR_RESULT))
9201 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9202 spy->consumeMotionPointerDown(1);
9203 window->consumeMotionPointerDown(2);
9204
9205 // Spy window pilfers the pointers.
9206 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9207 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9208 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9209
9210 spy->assertNoEvents();
9211 window->assertNoEvents();
9212}
9213
9214/**
9215 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9216 * other windows should be canceled. If this results in the cancellation of all pointers for some
9217 * window, then that window should receive ACTION_CANCEL.
9218 */
9219TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9220 auto spy = createSpy();
9221 spy->setFrame(Rect(0, 0, 100, 100));
9222 auto window = createForeground();
9223 window->setFrame(Rect(0, 0, 200, 200));
9224
9225 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9226
9227 // First finger down on both spy and window
9228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9229 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9230 {10, 10}))
9231 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9232 window->consumeMotionDown();
9233 spy->consumeMotionDown();
9234
9235 // Second finger down on the spy and window
9236 const MotionEvent secondFingerDownEvent =
9237 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9238 .displayId(ADISPLAY_ID_DEFAULT)
9239 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009240 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9241 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009242 .build();
9243 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9244 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9245 InputEventInjectionSync::WAIT_FOR_RESULT))
9246 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9247 spy->consumeMotionPointerDown(1);
9248 window->consumeMotionPointerDown(1);
9249
9250 // Spy window pilfers the pointers.
9251 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9252 window->consumeMotionCancel();
9253
9254 spy->assertNoEvents();
9255 window->assertNoEvents();
9256}
9257
9258/**
9259 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9260 * be sent to other windows
9261 */
9262TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9263 auto spy = createSpy();
9264 spy->setFrame(Rect(0, 0, 100, 100));
9265 auto window = createForeground();
9266 window->setFrame(Rect(0, 0, 200, 200));
9267
9268 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9269
9270 // First finger down on both window and spy
9271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9272 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9273 {10, 10}))
9274 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9275 window->consumeMotionDown();
9276 spy->consumeMotionDown();
9277
9278 // Spy window pilfers the pointers.
9279 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9280 window->consumeMotionCancel();
9281
9282 // Second finger down on the window only
9283 const MotionEvent secondFingerDownEvent =
9284 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9285 .displayId(ADISPLAY_ID_DEFAULT)
9286 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009287 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9288 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009289 .build();
9290 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9291 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9292 InputEventInjectionSync::WAIT_FOR_RESULT))
9293 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9294 window->consumeMotionDown();
9295 window->assertNoEvents();
9296
9297 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9298 spy->consumeMotionMove();
9299 spy->assertNoEvents();
9300}
9301
Prabir Pradhand65552b2021-10-07 11:23:50 -07009302class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9303public:
9304 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9305 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9306 std::make_shared<FakeApplicationHandle>();
9307 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009308 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9309 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009310 overlay->setFocusable(false);
9311 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009312 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009313 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009314 overlay->setTrustedOverlay(true);
9315
9316 std::shared_ptr<FakeApplicationHandle> application =
9317 std::make_shared<FakeApplicationHandle>();
9318 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009319 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9320 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009321 window->setFocusable(true);
9322 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009323
9324 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9325 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9326 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009327 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009328 return {std::move(overlay), std::move(window)};
9329 }
9330
9331 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009332 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009333 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009334 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009335 }
9336
9337 void sendStylusEvent(int32_t action) {
9338 NotifyMotionArgs motionArgs =
9339 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9340 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009341 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009342 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009343 }
9344};
9345
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009346using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9347
9348TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
9349 ScopedSilentDeath _silentDeath;
9350
Prabir Pradhand65552b2021-10-07 11:23:50 -07009351 auto [overlay, window] = setupStylusOverlayScenario();
9352 overlay->setTrustedOverlay(false);
9353 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9354 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9355 ".* not a trusted overlay");
9356}
9357
9358TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9359 auto [overlay, window] = setupStylusOverlayScenario();
9360 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9361
9362 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9363 overlay->consumeMotionDown();
9364 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9365 overlay->consumeMotionUp();
9366
9367 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9368 window->consumeMotionDown();
9369 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9370 window->consumeMotionUp();
9371
9372 overlay->assertNoEvents();
9373 window->assertNoEvents();
9374}
9375
9376TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9377 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009378 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009379 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9380
9381 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9382 overlay->consumeMotionDown();
9383 window->consumeMotionDown();
9384 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9385 overlay->consumeMotionUp();
9386 window->consumeMotionUp();
9387
9388 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9389 window->consumeMotionDown();
9390 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9391 window->consumeMotionUp();
9392
9393 overlay->assertNoEvents();
9394 window->assertNoEvents();
9395}
9396
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009397/**
9398 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9399 * The scenario is as follows:
9400 * - The stylus interceptor overlay is configured as a spy window.
9401 * - The stylus interceptor spy receives the start of a new stylus gesture.
9402 * - It pilfers pointers and then configures itself to no longer be a spy.
9403 * - The stylus interceptor continues to receive the rest of the gesture.
9404 */
9405TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9406 auto [overlay, window] = setupStylusOverlayScenario();
9407 overlay->setSpy(true);
9408 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9409
9410 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9411 overlay->consumeMotionDown();
9412 window->consumeMotionDown();
9413
9414 // The interceptor pilfers the pointers.
9415 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9416 window->consumeMotionCancel();
9417
9418 // The interceptor configures itself so that it is no longer a spy.
9419 overlay->setSpy(false);
9420 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9421
9422 // It continues to receive the rest of the stylus gesture.
9423 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9424 overlay->consumeMotionMove();
9425 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9426 overlay->consumeMotionUp();
9427
9428 window->assertNoEvents();
9429}
9430
Prabir Pradhan5735a322022-04-11 17:23:34 +00009431struct User {
9432 int32_t mPid;
9433 int32_t mUid;
9434 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9435 std::unique_ptr<InputDispatcher>& mDispatcher;
9436
9437 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
9438 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9439
9440 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9441 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9442 ADISPLAY_ID_DEFAULT, {100, 200},
9443 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9444 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9445 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9446 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9447 }
9448
9449 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009450 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009451 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009452 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009453 mPolicyFlags);
9454 }
9455
9456 sp<FakeWindowHandle> createWindow() const {
9457 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9458 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009459 sp<FakeWindowHandle> window =
9460 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9461 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009462 window->setOwnerInfo(mPid, mUid);
9463 return window;
9464 }
9465};
9466
9467using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9468
9469TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
9470 auto owner = User(mDispatcher, 10, 11);
9471 auto window = owner.createWindow();
9472 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9473
9474 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9475 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9476 window->consumeMotionDown();
9477
9478 setFocusedWindow(window);
9479 window->consumeFocusEvent(true);
9480
9481 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9482 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9483 window->consumeKeyDown(ADISPLAY_ID_NONE);
9484}
9485
9486TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
9487 auto owner = User(mDispatcher, 10, 11);
9488 auto window = owner.createWindow();
9489 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9490
9491 auto rando = User(mDispatcher, 20, 21);
9492 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9493 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9494
9495 setFocusedWindow(window);
9496 window->consumeFocusEvent(true);
9497
9498 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9499 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9500 window->assertNoEvents();
9501}
9502
9503TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
9504 auto owner = User(mDispatcher, 10, 11);
9505 auto window = owner.createWindow();
9506 auto spy = owner.createWindow();
9507 spy->setSpy(true);
9508 spy->setTrustedOverlay(true);
9509 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9510
9511 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9512 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9513 spy->consumeMotionDown();
9514 window->consumeMotionDown();
9515}
9516
9517TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
9518 auto owner = User(mDispatcher, 10, 11);
9519 auto window = owner.createWindow();
9520
9521 auto rando = User(mDispatcher, 20, 21);
9522 auto randosSpy = rando.createWindow();
9523 randosSpy->setSpy(true);
9524 randosSpy->setTrustedOverlay(true);
9525 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9526
9527 // The event is targeted at owner's window, so injection should succeed, but the spy should
9528 // not receive the event.
9529 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9530 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9531 randosSpy->assertNoEvents();
9532 window->consumeMotionDown();
9533}
9534
9535TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
9536 auto owner = User(mDispatcher, 10, 11);
9537 auto window = owner.createWindow();
9538
9539 auto rando = User(mDispatcher, 20, 21);
9540 auto randosSpy = rando.createWindow();
9541 randosSpy->setSpy(true);
9542 randosSpy->setTrustedOverlay(true);
9543 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9544
9545 // A user that has injection permission can inject into any window.
9546 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9547 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9548 ADISPLAY_ID_DEFAULT));
9549 randosSpy->consumeMotionDown();
9550 window->consumeMotionDown();
9551
9552 setFocusedWindow(randosSpy);
9553 randosSpy->consumeFocusEvent(true);
9554
9555 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9556 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9557 window->assertNoEvents();
9558}
9559
9560TEST_F(InputDispatcherTargetedInjectionTest, CanGenerateActionOutsideToOtherUids) {
9561 auto owner = User(mDispatcher, 10, 11);
9562 auto window = owner.createWindow();
9563
9564 auto rando = User(mDispatcher, 20, 21);
9565 auto randosWindow = rando.createWindow();
9566 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9567 randosWindow->setWatchOutsideTouch(true);
9568 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9569
9570 // We allow generation of ACTION_OUTSIDE events into windows owned by different uids.
9571 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9572 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9573 window->consumeMotionDown();
9574 randosWindow->consumeMotionOutside();
9575}
9576
Garfield Tane84e6f92019-08-29 17:28:41 -07009577} // namespace android::inputdispatcher