blob: f6f02d82413225ec03dc44c61d0e164d8f849334 [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
Patrick Williamsd828f302023-04-28 17:52:08 -05003948 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003949 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.
Patrick Williamsd828f302023-04-28 17:52:08 -05003962 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003963
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);
Patrick Williamsd828f302023-04-28 17:52:08 -05003978 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003979
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));
Patrick Williamsd828f302023-04-28 17:52:08 -05004025 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004026 }
4027
4028 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4029 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004030 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004031 }
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
Patrick Williamsd828f302023-04-28 17:52:08 -05005218 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
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
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005538/**
5539 * Two windows, one on the left and another on the right. The left window is slippery. The right
5540 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5541 * touch moves from the left window into the right window, the gesture should continue to go to the
5542 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5543 * reproduces a crash.
5544 */
5545TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5546 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5547
5548 sp<FakeWindowHandle> leftSlipperyWindow =
5549 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5550 leftSlipperyWindow->setSlippery(true);
5551 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5552
5553 sp<FakeWindowHandle> rightDropTouchesWindow =
5554 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5555 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5556 rightDropTouchesWindow->setDropInput(true);
5557
5558 mDispatcher->setInputWindows(
5559 {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}});
5560
5561 // Start touch in the left window
5562 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5563 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5564 .build());
5565 leftSlipperyWindow->consumeMotionDown();
5566
5567 // And move it into the right window
5568 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5569 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5570 .build());
5571
5572 // Since the right window isn't eligible to receive input, touch does not slip.
5573 // The left window continues to receive the gesture.
5574 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5575 rightDropTouchesWindow->assertNoEvents();
5576}
5577
Garfield Tan1c7bc862020-01-28 13:24:04 -08005578class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5579protected:
5580 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5581 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5582
Chris Yea209fde2020-07-22 13:54:51 -07005583 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005584 sp<FakeWindowHandle> mWindow;
5585
5586 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005587 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005588 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Prabir Pradhana41d2442023-04-20 21:30:40 +00005589 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Prabir Pradhan87112a72023-04-20 19:13:39 +00005590 mDispatcher->requestRefreshConfiguration();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005591 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
5592 ASSERT_EQ(OK, mDispatcher->start());
5593
5594 setUpWindow();
5595 }
5596
5597 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005598 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005599 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005600
Vishnu Nair47074b82020-08-14 11:54:47 -07005601 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005602 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005603 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005604 mWindow->consumeFocusEvent(true);
5605 }
5606
Chris Ye2ad95392020-09-01 13:44:44 -07005607 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005608 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005609 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005610 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005611 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005612
5613 // Window should receive key down event.
5614 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5615 }
5616
5617 void expectKeyRepeatOnce(int32_t repeatCount) {
5618 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5619 InputEvent* repeatEvent = mWindow->consume();
5620 ASSERT_NE(nullptr, repeatEvent);
5621
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005622 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005623
5624 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5625 uint32_t eventAction = repeatKeyEvent->getAction();
5626 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5627 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5628 }
5629
Chris Ye2ad95392020-09-01 13:44:44 -07005630 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005631 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005632 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005633 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005634 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005635
5636 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005637 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005638 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005639 }
5640};
5641
5642TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005643 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005644 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5645 expectKeyRepeatOnce(repeatCount);
5646 }
5647}
5648
5649TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005650 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005651 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5652 expectKeyRepeatOnce(repeatCount);
5653 }
Harry Cutts33476232023-01-30 19:57:29 +00005654 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005655 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005656 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5657 expectKeyRepeatOnce(repeatCount);
5658 }
5659}
5660
5661TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005662 sendAndConsumeKeyDown(/*deviceId=*/1);
5663 expectKeyRepeatOnce(/*repeatCount=*/1);
5664 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005665 mWindow->assertNoEvents();
5666}
5667
5668TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005669 sendAndConsumeKeyDown(/*deviceId=*/1);
5670 expectKeyRepeatOnce(/*repeatCount=*/1);
5671 sendAndConsumeKeyDown(/*deviceId=*/2);
5672 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005673 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005674 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005675 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005676 expectKeyRepeatOnce(/*repeatCount=*/2);
5677 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005678 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005679 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005680 mWindow->assertNoEvents();
5681}
5682
5683TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005684 sendAndConsumeKeyDown(/*deviceId=*/1);
5685 expectKeyRepeatOnce(/*repeatCount=*/1);
5686 sendAndConsumeKeyDown(/*deviceId=*/2);
5687 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005688 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005689 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005690 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005691 mWindow->assertNoEvents();
5692}
5693
liushenxiang42232912021-05-21 20:24:09 +08005694TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5695 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005696 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005697 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005698 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5699 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5700 mWindow->assertNoEvents();
5701}
5702
Garfield Tan1c7bc862020-01-28 13:24:04 -08005703TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005704 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005705 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005706 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5707 InputEvent* repeatEvent = mWindow->consume();
5708 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5709 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5710 IdGenerator::getSource(repeatEvent->getId()));
5711 }
5712}
5713
5714TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005715 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005716 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005717
5718 std::unordered_set<int32_t> idSet;
5719 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5720 InputEvent* repeatEvent = mWindow->consume();
5721 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5722 int32_t id = repeatEvent->getId();
5723 EXPECT_EQ(idSet.end(), idSet.find(id));
5724 idSet.insert(id);
5725 }
5726}
5727
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005728/* Test InputDispatcher for MultiDisplay */
5729class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5730public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005731 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005732 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005733
Chris Yea209fde2020-07-22 13:54:51 -07005734 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005735 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005736 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005737
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005738 // Set focus window for primary display, but focused display would be second one.
5739 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005740 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005741 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005742 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005743 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005744
Chris Yea209fde2020-07-22 13:54:51 -07005745 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005746 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005747 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005748 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005749 // Set focus display to second one.
5750 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5751 // Set focus window for second display.
5752 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005753 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005754 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005755 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005756 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005757 }
5758
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005759 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005760 InputDispatcherTest::TearDown();
5761
Chris Yea209fde2020-07-22 13:54:51 -07005762 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005763 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005764 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005765 windowInSecondary.clear();
5766 }
5767
5768protected:
Chris Yea209fde2020-07-22 13:54:51 -07005769 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005770 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005771 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005772 sp<FakeWindowHandle> windowInSecondary;
5773};
5774
5775TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5776 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5778 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5779 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005780 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005781 windowInSecondary->assertNoEvents();
5782
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005783 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005784 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5785 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5786 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005787 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005788 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005789}
5790
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005791TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005792 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5794 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005795 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005796 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005797 windowInSecondary->assertNoEvents();
5798
5799 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005801 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005802 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005803 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005804
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005805 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005806 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005807
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005808 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005809 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005810 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005811
5812 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005813 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005814 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005815 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005816 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005817 windowInSecondary->assertNoEvents();
5818}
5819
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005820// Test per-display input monitors for motion event.
5821TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005822 FakeMonitorReceiver monitorInPrimary =
5823 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5824 FakeMonitorReceiver monitorInSecondary =
5825 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005826
5827 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5829 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5830 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005831 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005832 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005833 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005834 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005835
5836 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5838 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5839 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005840 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005841 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005842 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005843 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005844
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005845 // Lift up the touch from the second display
5846 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5847 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5848 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5849 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5850 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5851
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005852 // Test inject a non-pointer motion event.
5853 // If specific a display, it will dispatch to the focused window of particular display,
5854 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5856 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5857 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005858 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005859 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005860 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005861 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005862}
5863
5864// Test per-display input monitors for key event.
5865TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005866 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005867 FakeMonitorReceiver monitorInPrimary =
5868 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5869 FakeMonitorReceiver monitorInSecondary =
5870 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005871
5872 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005873 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5874 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005875 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005876 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005877 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005878 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005879}
5880
Vishnu Nair958da932020-08-21 17:12:37 -07005881TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
5882 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005883 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005884 secondWindowInPrimary->setFocusable(true);
5885 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
5886 setFocusedWindow(secondWindowInPrimary);
5887 windowInPrimary->consumeFocusEvent(false);
5888 secondWindowInPrimary->consumeFocusEvent(true);
5889
5890 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005891 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
5892 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005893 windowInPrimary->assertNoEvents();
5894 windowInSecondary->assertNoEvents();
5895 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5896}
5897
Arthur Hungdfd528e2021-12-08 13:23:04 +00005898TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
5899 FakeMonitorReceiver monitorInPrimary =
5900 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5901 FakeMonitorReceiver monitorInSecondary =
5902 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
5903
5904 // Test touch down on primary display.
5905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5906 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5907 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5908 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5909 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5910
5911 // Test touch down on second display.
5912 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5913 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5915 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
5916 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
5917
5918 // Trigger cancel touch.
5919 mDispatcher->cancelCurrentTouch();
5920 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5921 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5922 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
5923 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
5924
5925 // Test inject a move motion event, no window/monitor should receive the event.
5926 ASSERT_EQ(InputEventInjectionResult::FAILED,
5927 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5928 ADISPLAY_ID_DEFAULT, {110, 200}))
5929 << "Inject motion event should return InputEventInjectionResult::FAILED";
5930 windowInPrimary->assertNoEvents();
5931 monitorInPrimary.assertNoEvents();
5932
5933 ASSERT_EQ(InputEventInjectionResult::FAILED,
5934 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5935 SECOND_DISPLAY_ID, {110, 200}))
5936 << "Inject motion event should return InputEventInjectionResult::FAILED";
5937 windowInSecondary->assertNoEvents();
5938 monitorInSecondary.assertNoEvents();
5939}
5940
Jackal Guof9696682018-10-05 12:23:23 +08005941class InputFilterTest : public InputDispatcherTest {
5942protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005943 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
5944 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08005945 NotifyMotionArgs motionArgs;
5946
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005947 motionArgs =
5948 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005949 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005950 motionArgs =
5951 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005952 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005953 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005954 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005955 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
5956 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08005957 } else {
5958 mFakePolicy->assertFilterInputEventWasNotCalled();
5959 }
5960 }
5961
5962 void testNotifyKey(bool expectToBeFiltered) {
5963 NotifyKeyArgs keyArgs;
5964
5965 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005966 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08005967 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005968 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005969 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005970
5971 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08005972 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08005973 } else {
5974 mFakePolicy->assertFilterInputEventWasNotCalled();
5975 }
5976 }
5977};
5978
5979// Test InputFilter for MotionEvent
5980TEST_F(InputFilterTest, MotionEvent_InputFilter) {
5981 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
5982 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5983 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5984
5985 // Enable InputFilter
5986 mDispatcher->setInputFilterEnabled(true);
5987 // Test touch on both primary and second display, and check if both events are filtered.
5988 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
5989 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
5990
5991 // Disable InputFilter
5992 mDispatcher->setInputFilterEnabled(false);
5993 // Test touch on both primary and second display, and check if both events aren't filtered.
5994 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5995 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5996}
5997
5998// Test InputFilter for KeyEvent
5999TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6000 // Since the InputFilter is disabled by default, check if key event aren't filtered.
6001 testNotifyKey(/*expectToBeFiltered*/ false);
6002
6003 // Enable InputFilter
6004 mDispatcher->setInputFilterEnabled(true);
6005 // Send a key event, and check if it is filtered.
6006 testNotifyKey(/*expectToBeFiltered*/ true);
6007
6008 // Disable InputFilter
6009 mDispatcher->setInputFilterEnabled(false);
6010 // Send a key event, and check if it isn't filtered.
6011 testNotifyKey(/*expectToBeFiltered*/ false);
6012}
6013
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006014// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6015// logical display coordinate space.
6016TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6017 ui::Transform firstDisplayTransform;
6018 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6019 ui::Transform secondDisplayTransform;
6020 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6021
6022 std::vector<gui::DisplayInfo> displayInfos(2);
6023 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6024 displayInfos[0].transform = firstDisplayTransform;
6025 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6026 displayInfos[1].transform = secondDisplayTransform;
6027
Patrick Williamsd828f302023-04-28 17:52:08 -05006028 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006029
6030 // Enable InputFilter
6031 mDispatcher->setInputFilterEnabled(true);
6032
6033 // Ensure the correct transforms are used for the displays.
6034 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
6035 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
6036}
6037
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006038class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6039protected:
6040 virtual void SetUp() override {
6041 InputDispatcherTest::SetUp();
6042
6043 /**
6044 * We don't need to enable input filter to test the injected event policy, but we enabled it
6045 * here to make the tests more realistic, since this policy only matters when inputfilter is
6046 * on.
6047 */
6048 mDispatcher->setInputFilterEnabled(true);
6049
6050 std::shared_ptr<InputApplicationHandle> application =
6051 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006052 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6053 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006054
6055 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6056 mWindow->setFocusable(true);
6057 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6058 setFocusedWindow(mWindow);
6059 mWindow->consumeFocusEvent(true);
6060 }
6061
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006062 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6063 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006064 KeyEvent event;
6065
6066 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6067 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6068 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006069 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006070 const int32_t additionalPolicyFlags =
6071 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6072 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006073 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006074 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6075 policyFlags | additionalPolicyFlags));
6076
6077 InputEvent* received = mWindow->consume();
6078 ASSERT_NE(nullptr, received);
6079 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006080 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006081 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
6082 ASSERT_EQ(flags, keyEvent.getFlags());
6083 }
6084
6085 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6086 int32_t flags) {
6087 MotionEvent event;
6088 PointerProperties pointerProperties[1];
6089 PointerCoords pointerCoords[1];
6090 pointerProperties[0].clear();
6091 pointerProperties[0].id = 0;
6092 pointerCoords[0].clear();
6093 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6094 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6095
6096 ui::Transform identityTransform;
6097 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6098 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6099 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6100 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6101 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006102 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006103 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006104 /*pointerCount*/ 1, pointerProperties, pointerCoords);
6105
6106 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006108 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006109 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6110 policyFlags | additionalPolicyFlags));
6111
6112 InputEvent* received = mWindow->consume();
6113 ASSERT_NE(nullptr, received);
6114 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006115 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006116 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
6117 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006118 }
6119
6120private:
6121 sp<FakeWindowHandle> mWindow;
6122};
6123
6124TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006125 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6126 // filter. Without it, the event will no different from a regularly injected event, and the
6127 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006128 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6129 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006130}
6131
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006132TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006133 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006134 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006135 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6136}
6137
6138TEST_F(InputFilterInjectionPolicyTest,
6139 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6140 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006141 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006142 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006143}
6144
6145TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006146 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6147 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006148}
6149
chaviwfd6d3512019-03-25 13:23:49 -07006150class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006151 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006152 InputDispatcherTest::SetUp();
6153
Chris Yea209fde2020-07-22 13:54:51 -07006154 std::shared_ptr<FakeApplicationHandle> application =
6155 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006156 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006157 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006158 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006159
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006160 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006161 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006162 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006163
6164 // Set focused application.
6165 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006166 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006167
6168 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00006169 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006170 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006171 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006172 }
6173
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006174 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006175 InputDispatcherTest::TearDown();
6176
6177 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006178 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006179 }
6180
6181protected:
6182 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006183 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006184 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006185};
6186
6187// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6188// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6189// the onPointerDownOutsideFocus callback.
6190TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006192 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6193 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006194 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006195 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006196
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006197 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006198 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6199}
6200
6201// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6202// DOWN on the window that doesn't have focus. Ensure no window received the
6203// onPointerDownOutsideFocus callback.
6204TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006206 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006207 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006208 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006209
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006210 ASSERT_TRUE(mDispatcher->waitForIdle());
6211 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006212}
6213
6214// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6215// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6216TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6218 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006219 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006220 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006221
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006222 ASSERT_TRUE(mDispatcher->waitForIdle());
6223 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006224}
6225
6226// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6227// DOWN on the window that already has focus. Ensure no window received the
6228// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006229TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006230 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006231 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006232 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006233 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006234 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006235
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006236 ASSERT_TRUE(mDispatcher->waitForIdle());
6237 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006238}
6239
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006240// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6241// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6242TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6243 const MotionEvent event =
6244 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6245 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006246 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006247 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6248 .build();
6249 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6250 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6251 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6252
6253 ASSERT_TRUE(mDispatcher->waitForIdle());
6254 mFakePolicy->assertOnPointerDownWasNotCalled();
6255 // Ensure that the unfocused window did not receive any FOCUS events.
6256 mUnfocusedWindow->assertNoEvents();
6257}
6258
chaviwaf87b3e2019-10-01 16:59:28 -07006259// These tests ensures we can send touch events to a single client when there are multiple input
6260// windows that point to the same client token.
6261class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6262 virtual void SetUp() override {
6263 InputDispatcherTest::SetUp();
6264
Chris Yea209fde2020-07-22 13:54:51 -07006265 std::shared_ptr<FakeApplicationHandle> application =
6266 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006267 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6268 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006269 mWindow1->setFrame(Rect(0, 0, 100, 100));
6270
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006271 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6272 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006273 mWindow2->setFrame(Rect(100, 100, 200, 200));
6274
Arthur Hung72d8dc32020-03-28 00:48:39 +00006275 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006276 }
6277
6278protected:
6279 sp<FakeWindowHandle> mWindow1;
6280 sp<FakeWindowHandle> mWindow2;
6281
6282 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006283 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006284 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6285 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006286 }
6287
6288 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6289 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006290 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006291 InputEvent* event = window->consume();
6292
6293 ASSERT_NE(nullptr, event) << name.c_str()
6294 << ": consumer should have returned non-NULL event.";
6295
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006296 ASSERT_EQ(InputEventType::MOTION, event->getType())
6297 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006298
6299 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006300 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006301 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006302
6303 for (size_t i = 0; i < points.size(); i++) {
6304 float expectedX = points[i].x;
6305 float expectedY = points[i].y;
6306
6307 EXPECT_EQ(expectedX, motionEvent.getX(i))
6308 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6309 << ", got " << motionEvent.getX(i);
6310 EXPECT_EQ(expectedY, motionEvent.getY(i))
6311 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6312 << ", got " << motionEvent.getY(i);
6313 }
6314 }
chaviw9eaa22c2020-07-01 16:21:27 -07006315
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006316 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006317 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006318 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6319 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006320
6321 // Always consume from window1 since it's the window that has the InputReceiver
6322 consumeMotionEvent(mWindow1, action, expectedPoints);
6323 }
chaviwaf87b3e2019-10-01 16:59:28 -07006324};
6325
6326TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6327 // Touch Window 1
6328 PointF touchedPoint = {10, 10};
6329 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006330 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006331
6332 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006333 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006334
6335 // Touch Window 2
6336 touchedPoint = {150, 150};
6337 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006338 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006339}
6340
chaviw9eaa22c2020-07-01 16:21:27 -07006341TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6342 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006343 mWindow2->setWindowScale(0.5f, 0.5f);
6344
6345 // Touch Window 1
6346 PointF touchedPoint = {10, 10};
6347 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006348 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006349 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006350 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006351
6352 // Touch Window 2
6353 touchedPoint = {150, 150};
6354 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006355 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6356 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006357
chaviw9eaa22c2020-07-01 16:21:27 -07006358 // Update the transform so rotation is set
6359 mWindow2->setWindowTransform(0, -1, 1, 0);
6360 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6361 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006362}
6363
chaviw9eaa22c2020-07-01 16:21:27 -07006364TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006365 mWindow2->setWindowScale(0.5f, 0.5f);
6366
6367 // Touch Window 1
6368 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6369 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006370 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006371
6372 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006373 touchedPoints.push_back(PointF{150, 150});
6374 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006375 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006376
chaviw9eaa22c2020-07-01 16:21:27 -07006377 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006378 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006379 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006380
chaviw9eaa22c2020-07-01 16:21:27 -07006381 // Update the transform so rotation is set for Window 2
6382 mWindow2->setWindowTransform(0, -1, 1, 0);
6383 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006384 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006385}
6386
chaviw9eaa22c2020-07-01 16:21:27 -07006387TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006388 mWindow2->setWindowScale(0.5f, 0.5f);
6389
6390 // Touch Window 1
6391 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6392 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006393 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006394
6395 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006396 touchedPoints.push_back(PointF{150, 150});
6397 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006398
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006399 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006400
6401 // Move both windows
6402 touchedPoints = {{20, 20}, {175, 175}};
6403 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6404 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6405
chaviw9eaa22c2020-07-01 16:21:27 -07006406 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006407
chaviw9eaa22c2020-07-01 16:21:27 -07006408 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006409 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006410 expectedPoints.pop_back();
6411
6412 // Touch Window 2
6413 mWindow2->setWindowTransform(0, -1, 1, 0);
6414 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006415 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006416
6417 // Move both windows
6418 touchedPoints = {{20, 20}, {175, 175}};
6419 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6420 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6421
6422 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006423}
6424
6425TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6426 mWindow1->setWindowScale(0.5f, 0.5f);
6427
6428 // Touch Window 1
6429 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6430 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006431 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006432
6433 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006434 touchedPoints.push_back(PointF{150, 150});
6435 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006436
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006437 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006438
6439 // Move both windows
6440 touchedPoints = {{20, 20}, {175, 175}};
6441 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6442 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6443
chaviw9eaa22c2020-07-01 16:21:27 -07006444 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006445}
6446
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006447/**
6448 * When one of the windows is slippery, the touch should not slip into the other window with the
6449 * same input channel.
6450 */
6451TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6452 mWindow1->setSlippery(true);
6453 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6454
6455 // Touch down in window 1
6456 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6457 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6458 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6459
6460 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6461 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6462 // getting generated.
6463 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6464 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6465
6466 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6467}
6468
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006469class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6470 virtual void SetUp() override {
6471 InputDispatcherTest::SetUp();
6472
Chris Yea209fde2020-07-22 13:54:51 -07006473 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006474 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006475 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6476 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006477 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006478 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006479 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006480
6481 // Set focused application.
6482 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6483
6484 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006485 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006486 mWindow->consumeFocusEvent(true);
6487 }
6488
6489 virtual void TearDown() override {
6490 InputDispatcherTest::TearDown();
6491 mWindow.clear();
6492 }
6493
6494protected:
Chris Yea209fde2020-07-22 13:54:51 -07006495 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006496 sp<FakeWindowHandle> mWindow;
6497 static constexpr PointF WINDOW_LOCATION = {20, 20};
6498
6499 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006500 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006501 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6502 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006503 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006504 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6505 WINDOW_LOCATION));
6506 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006507
6508 sp<FakeWindowHandle> addSpyWindow() {
6509 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006510 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006511 spy->setTrustedOverlay(true);
6512 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006513 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006514 spy->setDispatchingTimeout(30ms);
6515 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6516 return spy;
6517 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006518};
6519
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006520// Send a tap and respond, which should not cause an ANR.
6521TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6522 tapOnWindow();
6523 mWindow->consumeMotionDown();
6524 mWindow->consumeMotionUp();
6525 ASSERT_TRUE(mDispatcher->waitForIdle());
6526 mFakePolicy->assertNotifyAnrWasNotCalled();
6527}
6528
6529// Send a regular key and respond, which should not cause an ANR.
6530TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006531 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006532 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6533 ASSERT_TRUE(mDispatcher->waitForIdle());
6534 mFakePolicy->assertNotifyAnrWasNotCalled();
6535}
6536
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006537TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6538 mWindow->setFocusable(false);
6539 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6540 mWindow->consumeFocusEvent(false);
6541
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006542 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006543 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6544 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6545 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006546 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006547 // Key will not go to window because we have no focused window.
6548 // The 'no focused window' ANR timer should start instead.
6549
6550 // Now, the focused application goes away.
6551 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6552 // The key should get dropped and there should be no ANR.
6553
6554 ASSERT_TRUE(mDispatcher->waitForIdle());
6555 mFakePolicy->assertNotifyAnrWasNotCalled();
6556}
6557
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006558// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006559// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6560// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006561TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006562 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006563 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6564 WINDOW_LOCATION));
6565
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006566 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6567 ASSERT_TRUE(sequenceNum);
6568 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006569 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006570
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006571 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006572 mWindow->consumeMotionEvent(
6573 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006574 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006575 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006576}
6577
6578// Send a key to the app and have the app not respond right away.
6579TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6580 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006581 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006582 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6583 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006584 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006585 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006586 ASSERT_TRUE(mDispatcher->waitForIdle());
6587}
6588
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006589// We have a focused application, but no focused window
6590TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006591 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006592 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6593 mWindow->consumeFocusEvent(false);
6594
6595 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006597 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6598 WINDOW_LOCATION));
6599 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6600 mDispatcher->waitForIdle();
6601 mFakePolicy->assertNotifyAnrWasNotCalled();
6602
6603 // Once a focused event arrives, we get an ANR for this application
6604 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6605 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006606 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006607 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6608 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006609 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006610 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006611 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006612 ASSERT_TRUE(mDispatcher->waitForIdle());
6613}
6614
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006615/**
6616 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6617 * there will not be an ANR.
6618 */
6619TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6620 mWindow->setFocusable(false);
6621 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6622 mWindow->consumeFocusEvent(false);
6623
6624 KeyEvent event;
6625 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6626 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6627
6628 // Define a valid key down event that is stale (too old).
6629 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6630 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006631 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006632
6633 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6634
6635 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006636 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006637 InputEventInjectionSync::WAIT_FOR_RESULT,
6638 INJECT_EVENT_TIMEOUT, policyFlags);
6639 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6640 << "Injection should fail because the event is stale";
6641
6642 ASSERT_TRUE(mDispatcher->waitForIdle());
6643 mFakePolicy->assertNotifyAnrWasNotCalled();
6644 mWindow->assertNoEvents();
6645}
6646
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006647// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006648// Make sure that we don't notify policy twice about the same ANR.
6649TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006650 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006651 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6652 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006653
6654 // Once a focused event arrives, we get an ANR for this application
6655 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6656 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006657 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006658 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6659 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006660 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006661 const std::chrono::duration appTimeout =
6662 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6663 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006664
Vishnu Naire4df8752022-09-08 09:17:55 -07006665 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006666 // ANR should not be raised again. It is up to policy to do that if it desires.
6667 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006668
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006669 // If we now get a focused window, the ANR should stop, but the policy handles that via
6670 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006671 ASSERT_TRUE(mDispatcher->waitForIdle());
6672}
6673
6674// We have a focused application, but no focused window
6675TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006676 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006677 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6678 mWindow->consumeFocusEvent(false);
6679
6680 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006681 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006682 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006683 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6684 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006685
Vishnu Naire4df8752022-09-08 09:17:55 -07006686 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6687 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006688
6689 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006690 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006691 ASSERT_TRUE(mDispatcher->waitForIdle());
6692 mWindow->assertNoEvents();
6693}
6694
6695/**
6696 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6697 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6698 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6699 * the ANR mechanism should still work.
6700 *
6701 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6702 * DOWN event, while not responding on the second one.
6703 */
6704TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6705 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6706 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6707 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6708 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6709 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006710 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006711
6712 // Now send ACTION_UP, with identical timestamp
6713 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6714 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6715 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6716 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006717 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006718
6719 // We have now sent down and up. Let's consume first event and then ANR on the second.
6720 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6721 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006722 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006723}
6724
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006725// A spy window can receive an ANR
6726TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6727 sp<FakeWindowHandle> spy = addSpyWindow();
6728
6729 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6730 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6731 WINDOW_LOCATION));
6732 mWindow->consumeMotionDown();
6733
6734 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6735 ASSERT_TRUE(sequenceNum);
6736 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006737 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006738
6739 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006740 spy->consumeMotionEvent(
6741 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006742 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006743 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006744}
6745
6746// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006747// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006748TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6749 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006750
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6752 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006753 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006755
6756 // Stuck on the ACTION_UP
6757 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006758 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006759
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006760 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006761 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006762 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6763 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006764
6765 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6766 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006767 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006768 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006769 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006770}
6771
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006772// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006773// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006774TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6775 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006776
6777 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006778 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6779 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006780
6781 mWindow->consumeMotionDown();
6782 // Stuck on the ACTION_UP
6783 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006784 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006785
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006786 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006787 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006788 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6789 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006790
6791 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6792 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006793 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006794 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006795 spy->assertNoEvents();
6796}
6797
6798TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6799 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6800
6801 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6802
6803 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6804 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6805 WINDOW_LOCATION));
6806
6807 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6808 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6809 ASSERT_TRUE(consumeSeq);
6810
Prabir Pradhanedd96402022-02-15 01:46:16 -08006811 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006812
6813 monitor.finishEvent(*consumeSeq);
6814 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6815
6816 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006817 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006818}
6819
6820// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6821// process events, you don't get an anr. When the window later becomes unresponsive again, you
6822// get an ANR again.
6823// 1. tap -> block on ACTION_UP -> receive ANR
6824// 2. consume all pending events (= queue becomes healthy again)
6825// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6826TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6827 tapOnWindow();
6828
6829 mWindow->consumeMotionDown();
6830 // Block on ACTION_UP
6831 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006832 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006833 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6834 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006835 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006836 mWindow->assertNoEvents();
6837
6838 tapOnWindow();
6839 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006840 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006841 mWindow->consumeMotionUp();
6842
6843 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006844 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006845 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006846 mWindow->assertNoEvents();
6847}
6848
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006849// If a connection remains unresponsive for a while, make sure policy is only notified once about
6850// it.
6851TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006852 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006853 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6854 WINDOW_LOCATION));
6855
6856 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006857 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006858 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006859 // 'notifyConnectionUnresponsive' should only be called once per connection
6860 mFakePolicy->assertNotifyAnrWasNotCalled();
6861 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006862 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006863 mWindow->consumeMotionEvent(
6864 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006865 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006866 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006867 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006868 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006869}
6870
6871/**
6872 * If a window is processing a motion event, and then a key event comes in, the key event should
6873 * not to to the focused window until the motion is processed.
6874 *
6875 * Warning!!!
6876 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
6877 * and the injection timeout that we specify when injecting the key.
6878 * We must have the injection timeout (10ms) be smaller than
6879 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
6880 *
6881 * If that value changes, this test should also change.
6882 */
6883TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
6884 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6885 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6886
6887 tapOnWindow();
6888 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6889 ASSERT_TRUE(downSequenceNum);
6890 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6891 ASSERT_TRUE(upSequenceNum);
6892 // Don't finish the events yet, and send a key
6893 // Injection will "succeed" because we will eventually give up and send the key to the focused
6894 // window even if motions are still being processed. But because the injection timeout is short,
6895 // we will receive INJECTION_TIMED_OUT as the result.
6896
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006897 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006898 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006899 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6900 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006901 // Key will not be sent to the window, yet, because the window is still processing events
6902 // and the key remains pending, waiting for the touch events to be processed
6903 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6904 ASSERT_FALSE(keySequenceNum);
6905
6906 std::this_thread::sleep_for(500ms);
6907 // if we wait long enough though, dispatcher will give up, and still send the key
6908 // to the focused window, even though we have not yet finished the motion event
6909 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6910 mWindow->finishEvent(*downSequenceNum);
6911 mWindow->finishEvent(*upSequenceNum);
6912}
6913
6914/**
6915 * If a window is processing a motion event, and then a key event comes in, the key event should
6916 * not go to the focused window until the motion is processed.
6917 * If then a new motion comes in, then the pending key event should be going to the currently
6918 * focused window right away.
6919 */
6920TEST_F(InputDispatcherSingleWindowAnr,
6921 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
6922 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6923 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6924
6925 tapOnWindow();
6926 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6927 ASSERT_TRUE(downSequenceNum);
6928 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6929 ASSERT_TRUE(upSequenceNum);
6930 // Don't finish the events yet, and send a key
6931 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006932 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006933 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6934 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006935 // At this point, key is still pending, and should not be sent to the application yet.
6936 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6937 ASSERT_FALSE(keySequenceNum);
6938
6939 // Now tap down again. It should cause the pending key to go to the focused window right away.
6940 tapOnWindow();
6941 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
6942 // the other events yet. We can finish events in any order.
6943 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
6944 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
6945 mWindow->consumeMotionDown();
6946 mWindow->consumeMotionUp();
6947 mWindow->assertNoEvents();
6948}
6949
6950class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
6951 virtual void SetUp() override {
6952 InputDispatcherTest::SetUp();
6953
Chris Yea209fde2020-07-22 13:54:51 -07006954 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006955 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006956 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
6957 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006958 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006959 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006960 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006961
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006962 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
6963 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006964 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006965 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006966
6967 // Set focused application.
6968 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07006969 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006970
6971 // Expect one focus window exist in display.
6972 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006973 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006974 mFocusedWindow->consumeFocusEvent(true);
6975 }
6976
6977 virtual void TearDown() override {
6978 InputDispatcherTest::TearDown();
6979
6980 mUnfocusedWindow.clear();
6981 mFocusedWindow.clear();
6982 }
6983
6984protected:
Chris Yea209fde2020-07-22 13:54:51 -07006985 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006986 sp<FakeWindowHandle> mUnfocusedWindow;
6987 sp<FakeWindowHandle> mFocusedWindow;
6988 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
6989 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
6990 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
6991
6992 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
6993
6994 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
6995
6996private:
6997 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006999 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7000 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007002 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7003 location));
7004 }
7005};
7006
7007// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7008// should be ANR'd first.
7009TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007011 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7012 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007013 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007014 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007015 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007016 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007017 // We consumed all events, so no ANR
7018 ASSERT_TRUE(mDispatcher->waitForIdle());
7019 mFakePolicy->assertNotifyAnrWasNotCalled();
7020
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007021 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007022 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7023 FOCUSED_WINDOW_LOCATION));
7024 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7025 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007026
7027 const std::chrono::duration timeout =
7028 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007029 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007030 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7031 // sequence to make it consistent
7032 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007033 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007034 mFocusedWindow->consumeMotionDown();
7035 // This cancel is generated because the connection was unresponsive
7036 mFocusedWindow->consumeMotionCancel();
7037 mFocusedWindow->assertNoEvents();
7038 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007039 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007040 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7041 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007042 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007043}
7044
7045// If we have 2 windows with identical timeouts that are both unresponsive,
7046// it doesn't matter which order they should have ANR.
7047// But we should receive ANR for both.
7048TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7049 // Set the timeout for unfocused window to match the focused window
7050 mUnfocusedWindow->setDispatchingTimeout(10ms);
7051 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7052
7053 tapOnFocusedWindow();
7054 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08007055 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
7056 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
7057 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007058
7059 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007060 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
7061 mFocusedWindow->getToken() == anrConnectionToken2);
7062 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
7063 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007064
7065 ASSERT_TRUE(mDispatcher->waitForIdle());
7066 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007067
7068 mFocusedWindow->consumeMotionDown();
7069 mFocusedWindow->consumeMotionUp();
7070 mUnfocusedWindow->consumeMotionOutside();
7071
Prabir Pradhanedd96402022-02-15 01:46:16 -08007072 sp<IBinder> responsiveToken1, responsiveToken2;
7073 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
7074 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007075
7076 // Both applications should be marked as responsive, in any order
7077 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
7078 mFocusedWindow->getToken() == responsiveToken2);
7079 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
7080 mUnfocusedWindow->getToken() == responsiveToken2);
7081 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007082}
7083
7084// If a window is already not responding, the second tap on the same window should be ignored.
7085// We should also log an error to account for the dropped event (not tested here).
7086// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7087TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7088 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007089 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007090 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007091 // Receive the events, but don't respond
7092 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7093 ASSERT_TRUE(downEventSequenceNum);
7094 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7095 ASSERT_TRUE(upEventSequenceNum);
7096 const std::chrono::duration timeout =
7097 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007098 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007099
7100 // Tap once again
7101 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007102 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007103 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7104 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007105 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007106 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7107 FOCUSED_WINDOW_LOCATION));
7108 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7109 // valid touch target
7110 mUnfocusedWindow->assertNoEvents();
7111
7112 // Consume the first tap
7113 mFocusedWindow->finishEvent(*downEventSequenceNum);
7114 mFocusedWindow->finishEvent(*upEventSequenceNum);
7115 ASSERT_TRUE(mDispatcher->waitForIdle());
7116 // The second tap did not go to the focused window
7117 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007118 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007119 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7120 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007121 mFakePolicy->assertNotifyAnrWasNotCalled();
7122}
7123
7124// If you tap outside of all windows, there will not be ANR
7125TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007126 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007127 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7128 LOCATION_OUTSIDE_ALL_WINDOWS));
7129 ASSERT_TRUE(mDispatcher->waitForIdle());
7130 mFakePolicy->assertNotifyAnrWasNotCalled();
7131}
7132
7133// Since the focused window is paused, tapping on it should not produce any events
7134TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7135 mFocusedWindow->setPaused(true);
7136 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7137
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007138 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007139 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7140 FOCUSED_WINDOW_LOCATION));
7141
7142 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7143 ASSERT_TRUE(mDispatcher->waitForIdle());
7144 // Should not ANR because the window is paused, and touches shouldn't go to it
7145 mFakePolicy->assertNotifyAnrWasNotCalled();
7146
7147 mFocusedWindow->assertNoEvents();
7148 mUnfocusedWindow->assertNoEvents();
7149}
7150
7151/**
7152 * If a window is processing a motion event, and then a key event comes in, the key event should
7153 * not to to the focused window until the motion is processed.
7154 * If a different window becomes focused at this time, the key should go to that window instead.
7155 *
7156 * Warning!!!
7157 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7158 * and the injection timeout that we specify when injecting the key.
7159 * We must have the injection timeout (10ms) be smaller than
7160 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7161 *
7162 * If that value changes, this test should also change.
7163 */
7164TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7165 // Set a long ANR timeout to prevent it from triggering
7166 mFocusedWindow->setDispatchingTimeout(2s);
7167 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7168
7169 tapOnUnfocusedWindow();
7170 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7171 ASSERT_TRUE(downSequenceNum);
7172 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7173 ASSERT_TRUE(upSequenceNum);
7174 // Don't finish the events yet, and send a key
7175 // Injection will succeed because we will eventually give up and send the key to the focused
7176 // window even if motions are still being processed.
7177
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007178 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007179 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7180 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007181 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007182 // Key will not be sent to the window, yet, because the window is still processing events
7183 // and the key remains pending, waiting for the touch events to be processed
7184 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7185 ASSERT_FALSE(keySequenceNum);
7186
7187 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007188 mFocusedWindow->setFocusable(false);
7189 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007190 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007191 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007192
7193 // Focus events should precede the key events
7194 mUnfocusedWindow->consumeFocusEvent(true);
7195 mFocusedWindow->consumeFocusEvent(false);
7196
7197 // Finish the tap events, which should unblock dispatcher
7198 mUnfocusedWindow->finishEvent(*downSequenceNum);
7199 mUnfocusedWindow->finishEvent(*upSequenceNum);
7200
7201 // Now that all queues are cleared and no backlog in the connections, the key event
7202 // can finally go to the newly focused "mUnfocusedWindow".
7203 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7204 mFocusedWindow->assertNoEvents();
7205 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007206 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007207}
7208
7209// When the touch stream is split across 2 windows, and one of them does not respond,
7210// then ANR should be raised and the touch should be canceled for the unresponsive window.
7211// The other window should not be affected by that.
7212TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7213 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007214 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7215 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7216 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007217 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007218 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007219
7220 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007221 mDispatcher->notifyMotion(
7222 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7223 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007224
7225 const std::chrono::duration timeout =
7226 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007227 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007228
7229 mUnfocusedWindow->consumeMotionDown();
7230 mFocusedWindow->consumeMotionDown();
7231 // Focused window may or may not receive ACTION_MOVE
7232 // But it should definitely receive ACTION_CANCEL due to the ANR
7233 InputEvent* event;
7234 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7235 ASSERT_TRUE(moveOrCancelSequenceNum);
7236 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7237 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007238 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007239 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7240 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7241 mFocusedWindow->consumeMotionCancel();
7242 } else {
7243 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7244 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007245 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007246 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7247 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007248
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007249 mUnfocusedWindow->assertNoEvents();
7250 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007251 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007252}
7253
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007254/**
7255 * If we have no focused window, and a key comes in, we start the ANR timer.
7256 * The focused application should add a focused window before the timer runs out to prevent ANR.
7257 *
7258 * If the user touches another application during this time, the key should be dropped.
7259 * Next, if a new focused window comes in, without toggling the focused application,
7260 * then no ANR should occur.
7261 *
7262 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7263 * but in some cases the policy may not update the focused application.
7264 */
7265TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7266 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7267 std::make_shared<FakeApplicationHandle>();
7268 focusedApplication->setDispatchingTimeout(60ms);
7269 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7270 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7271 mFocusedWindow->setFocusable(false);
7272
7273 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7274 mFocusedWindow->consumeFocusEvent(false);
7275
7276 // Send a key. The ANR timer should start because there is no focused window.
7277 // 'focusedApplication' will get blamed if this timer completes.
7278 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007279 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007280 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7281 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
7282 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007283 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007284
7285 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7286 // then the injected touches won't cause the focused event to get dropped.
7287 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7288 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7289 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7290 // For this test, it means that the key would get delivered to the window once it becomes
7291 // focused.
7292 std::this_thread::sleep_for(10ms);
7293
7294 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007295 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7296 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7297 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007298
7299 // We do not consume the motion right away, because that would require dispatcher to first
7300 // process (== drop) the key event, and by that time, ANR will be raised.
7301 // Set the focused window first.
7302 mFocusedWindow->setFocusable(true);
7303 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7304 setFocusedWindow(mFocusedWindow);
7305 mFocusedWindow->consumeFocusEvent(true);
7306 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7307 // to another application. This could be a bug / behaviour in the policy.
7308
7309 mUnfocusedWindow->consumeMotionDown();
7310
7311 ASSERT_TRUE(mDispatcher->waitForIdle());
7312 // Should not ANR because we actually have a focused window. It was just added too slowly.
7313 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7314}
7315
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007316// These tests ensure we cannot send touch events to a window that's positioned behind a window
7317// that has feature NO_INPUT_CHANNEL.
7318// Layout:
7319// Top (closest to user)
7320// mNoInputWindow (above all windows)
7321// mBottomWindow
7322// Bottom (furthest from user)
7323class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7324 virtual void SetUp() override {
7325 InputDispatcherTest::SetUp();
7326
7327 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007328 mNoInputWindow =
7329 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7330 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007331 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007332 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007333 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7334 // It's perfectly valid for this window to not have an associated input channel
7335
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007336 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7337 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007338 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7339
7340 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7341 }
7342
7343protected:
7344 std::shared_ptr<FakeApplicationHandle> mApplication;
7345 sp<FakeWindowHandle> mNoInputWindow;
7346 sp<FakeWindowHandle> mBottomWindow;
7347};
7348
7349TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7350 PointF touchedPoint = {10, 10};
7351
Prabir Pradhan678438e2023-04-13 19:32:51 +00007352 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7353 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7354 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007355
7356 mNoInputWindow->assertNoEvents();
7357 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7358 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7359 // and therefore should prevent mBottomWindow from receiving touches
7360 mBottomWindow->assertNoEvents();
7361}
7362
7363/**
7364 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7365 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7366 */
7367TEST_F(InputDispatcherMultiWindowOcclusionTests,
7368 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007369 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7370 "Window with input channel and NO_INPUT_CHANNEL",
7371 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007372
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007373 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007374 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7375 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7376
7377 PointF touchedPoint = {10, 10};
7378
Prabir Pradhan678438e2023-04-13 19:32:51 +00007379 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7380 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7381 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007382
7383 mNoInputWindow->assertNoEvents();
7384 mBottomWindow->assertNoEvents();
7385}
7386
Vishnu Nair958da932020-08-21 17:12:37 -07007387class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7388protected:
7389 std::shared_ptr<FakeApplicationHandle> mApp;
7390 sp<FakeWindowHandle> mWindow;
7391 sp<FakeWindowHandle> mMirror;
7392
7393 virtual void SetUp() override {
7394 InputDispatcherTest::SetUp();
7395 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007396 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7397 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7398 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007399 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7400 mWindow->setFocusable(true);
7401 mMirror->setFocusable(true);
7402 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7403 }
7404};
7405
7406TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7407 // Request focus on a mirrored window
7408 setFocusedWindow(mMirror);
7409
7410 // window gets focused
7411 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007412 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7413 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007414 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7415}
7416
7417// A focused & mirrored window remains focused only if the window and its mirror are both
7418// focusable.
7419TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7420 setFocusedWindow(mMirror);
7421
7422 // window gets focused
7423 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7425 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007426 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7428 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007429 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7430
7431 mMirror->setFocusable(false);
7432 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7433
7434 // window loses focus since one of the windows associated with the token in not focusable
7435 mWindow->consumeFocusEvent(false);
7436
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007437 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7438 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007439 mWindow->assertNoEvents();
7440}
7441
7442// A focused & mirrored window remains focused until the window and its mirror both become
7443// invisible.
7444TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7445 setFocusedWindow(mMirror);
7446
7447 // window gets focused
7448 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007449 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7450 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007451 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7453 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007454 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7455
7456 mMirror->setVisible(false);
7457 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7458
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007459 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7460 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007461 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007462 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7463 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007464 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7465
7466 mWindow->setVisible(false);
7467 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7468
7469 // window loses focus only after all windows associated with the token become invisible.
7470 mWindow->consumeFocusEvent(false);
7471
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007472 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7473 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007474 mWindow->assertNoEvents();
7475}
7476
7477// A focused & mirrored window remains focused until both windows are removed.
7478TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7479 setFocusedWindow(mMirror);
7480
7481 // window gets focused
7482 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007483 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7484 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007485 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7487 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007488 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7489
7490 // single window is removed but the window token remains focused
7491 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7492
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007493 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7494 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007495 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007496 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7497 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007498 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7499
7500 // Both windows are removed
7501 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7502 mWindow->consumeFocusEvent(false);
7503
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007504 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7505 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007506 mWindow->assertNoEvents();
7507}
7508
7509// Focus request can be pending until one window becomes visible.
7510TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7511 // Request focus on an invisible mirror.
7512 mWindow->setVisible(false);
7513 mMirror->setVisible(false);
7514 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7515 setFocusedWindow(mMirror);
7516
7517 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007518 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007519 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7520 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007521
7522 mMirror->setVisible(true);
7523 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7524
7525 // window gets focused
7526 mWindow->consumeFocusEvent(true);
7527 // window gets the pending key event
7528 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7529}
Prabir Pradhan99987712020-11-10 18:43:05 -08007530
7531class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7532protected:
7533 std::shared_ptr<FakeApplicationHandle> mApp;
7534 sp<FakeWindowHandle> mWindow;
7535 sp<FakeWindowHandle> mSecondWindow;
7536
7537 void SetUp() override {
7538 InputDispatcherTest::SetUp();
7539 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007540 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007541 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007542 mSecondWindow =
7543 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007544 mSecondWindow->setFocusable(true);
7545
7546 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7547 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7548
7549 setFocusedWindow(mWindow);
7550 mWindow->consumeFocusEvent(true);
7551 }
7552
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007553 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007554 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007555 }
7556
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007557 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7558 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007559 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007560 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7561 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007562 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007563 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007564 }
7565};
7566
7567TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7568 // Ensure that capture cannot be obtained for unfocused windows.
7569 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7570 mFakePolicy->assertSetPointerCaptureNotCalled();
7571 mSecondWindow->assertNoEvents();
7572
7573 // Ensure that capture can be enabled from the focus window.
7574 requestAndVerifyPointerCapture(mWindow, true);
7575
7576 // Ensure that capture cannot be disabled from a window that does not have capture.
7577 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7578 mFakePolicy->assertSetPointerCaptureNotCalled();
7579
7580 // Ensure that capture can be disabled from the window with capture.
7581 requestAndVerifyPointerCapture(mWindow, false);
7582}
7583
7584TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007585 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007586
7587 setFocusedWindow(mSecondWindow);
7588
7589 // Ensure that the capture disabled event was sent first.
7590 mWindow->consumeCaptureEvent(false);
7591 mWindow->consumeFocusEvent(false);
7592 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007593 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007594
7595 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007596 notifyPointerCaptureChanged({});
7597 notifyPointerCaptureChanged(request);
7598 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007599 mWindow->assertNoEvents();
7600 mSecondWindow->assertNoEvents();
7601 mFakePolicy->assertSetPointerCaptureNotCalled();
7602}
7603
7604TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007605 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007606
7607 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007608 notifyPointerCaptureChanged({});
7609 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007610
7611 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007612 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007613 mWindow->consumeCaptureEvent(false);
7614 mWindow->assertNoEvents();
7615}
7616
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007617TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7618 requestAndVerifyPointerCapture(mWindow, true);
7619
7620 // The first window loses focus.
7621 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007622 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007623 mWindow->consumeCaptureEvent(false);
7624
7625 // Request Pointer Capture from the second window before the notification from InputReader
7626 // arrives.
7627 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007628 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007629
7630 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007631 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007632
7633 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007634 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007635
7636 mSecondWindow->consumeFocusEvent(true);
7637 mSecondWindow->consumeCaptureEvent(true);
7638}
7639
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007640TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7641 // App repeatedly enables and disables capture.
7642 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7643 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7644 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7645 mFakePolicy->assertSetPointerCaptureCalled(false);
7646 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7647 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7648
7649 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7650 // first request is now stale, this should do nothing.
7651 notifyPointerCaptureChanged(firstRequest);
7652 mWindow->assertNoEvents();
7653
7654 // InputReader notifies that the second request was enabled.
7655 notifyPointerCaptureChanged(secondRequest);
7656 mWindow->consumeCaptureEvent(true);
7657}
7658
Prabir Pradhan7092e262022-05-03 16:51:09 +00007659TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7660 requestAndVerifyPointerCapture(mWindow, true);
7661
7662 // App toggles pointer capture off and on.
7663 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7664 mFakePolicy->assertSetPointerCaptureCalled(false);
7665
7666 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7667 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7668
7669 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7670 // preceding "disable" request.
7671 notifyPointerCaptureChanged(enableRequest);
7672
7673 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7674 // any notifications.
7675 mWindow->assertNoEvents();
7676}
7677
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007678class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7679protected:
7680 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007681
7682 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7683 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7684
7685 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7686 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7687
7688 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7689 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7690 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7691 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7692 MAXIMUM_OBSCURING_OPACITY);
7693
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007694 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007695 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007696 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007697
7698 sp<FakeWindowHandle> mTouchWindow;
7699
7700 virtual void SetUp() override {
7701 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007702 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007703 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7704 }
7705
7706 virtual void TearDown() override {
7707 InputDispatcherTest::TearDown();
7708 mTouchWindow.clear();
7709 }
7710
chaviw3277faf2021-05-19 16:45:23 -05007711 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
7712 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007713 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007714 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007715 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007716 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007717 return window;
7718 }
7719
7720 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
7721 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7722 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007723 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007724 // Generate an arbitrary PID based on the UID
7725 window->setOwnerInfo(1777 + (uid % 10000), uid);
7726 return window;
7727 }
7728
7729 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007730 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7731 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7732 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007733 }
7734};
7735
7736TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007737 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007738 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007739 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007740
7741 touch();
7742
7743 mTouchWindow->assertNoEvents();
7744}
7745
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007746TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007747 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7748 const sp<FakeWindowHandle>& w =
7749 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7750 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7751
7752 touch();
7753
7754 mTouchWindow->assertNoEvents();
7755}
7756
7757TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007758 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7759 const sp<FakeWindowHandle>& w =
7760 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7761 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7762
7763 touch();
7764
7765 w->assertNoEvents();
7766}
7767
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007768TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007769 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7770 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007771
7772 touch();
7773
7774 mTouchWindow->consumeAnyMotionDown();
7775}
7776
7777TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007778 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007779 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007780 w->setFrame(Rect(0, 0, 50, 50));
7781 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007782
7783 touch({PointF{100, 100}});
7784
7785 mTouchWindow->consumeAnyMotionDown();
7786}
7787
7788TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007789 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007790 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007791 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7792
7793 touch();
7794
7795 mTouchWindow->consumeAnyMotionDown();
7796}
7797
7798TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7799 const sp<FakeWindowHandle>& w =
7800 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7801 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007802
7803 touch();
7804
7805 mTouchWindow->consumeAnyMotionDown();
7806}
7807
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007808TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7809 const sp<FakeWindowHandle>& w =
7810 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7811 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7812
7813 touch();
7814
7815 w->assertNoEvents();
7816}
7817
7818/**
7819 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
7820 * inside) while letting them pass-through. Note that even though touch passes through the occluding
7821 * window, the occluding window will still receive ACTION_OUTSIDE event.
7822 */
7823TEST_F(InputDispatcherUntrustedTouchesTest,
7824 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
7825 const sp<FakeWindowHandle>& w =
7826 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007827 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007828 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7829
7830 touch();
7831
7832 w->consumeMotionOutside();
7833}
7834
7835TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
7836 const sp<FakeWindowHandle>& w =
7837 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007838 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007839 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7840
7841 touch();
7842
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007843 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007844}
7845
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007846TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007847 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007848 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7849 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007850 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7851
7852 touch();
7853
7854 mTouchWindow->consumeAnyMotionDown();
7855}
7856
7857TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
7858 const sp<FakeWindowHandle>& w =
7859 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7860 MAXIMUM_OBSCURING_OPACITY);
7861 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007862
7863 touch();
7864
7865 mTouchWindow->consumeAnyMotionDown();
7866}
7867
7868TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007869 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007870 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7871 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007872 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7873
7874 touch();
7875
7876 mTouchWindow->assertNoEvents();
7877}
7878
7879TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
7880 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
7881 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007882 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7883 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007884 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007885 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7886 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007887 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7888
7889 touch();
7890
7891 mTouchWindow->assertNoEvents();
7892}
7893
7894TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
7895 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
7896 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007897 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7898 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007899 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007900 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7901 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007902 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7903
7904 touch();
7905
7906 mTouchWindow->consumeAnyMotionDown();
7907}
7908
7909TEST_F(InputDispatcherUntrustedTouchesTest,
7910 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
7911 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007912 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7913 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007914 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007915 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7916 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007917 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
7918
7919 touch();
7920
7921 mTouchWindow->consumeAnyMotionDown();
7922}
7923
7924TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
7925 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007926 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7927 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007928 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007929 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7930 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007931 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007932
7933 touch();
7934
7935 mTouchWindow->assertNoEvents();
7936}
7937
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007938TEST_F(InputDispatcherUntrustedTouchesTest,
7939 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
7940 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007941 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7942 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007943 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007944 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7945 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007946 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7947
7948 touch();
7949
7950 mTouchWindow->assertNoEvents();
7951}
7952
7953TEST_F(InputDispatcherUntrustedTouchesTest,
7954 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
7955 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007956 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7957 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007958 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007959 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7960 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007961 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7962
7963 touch();
7964
7965 mTouchWindow->consumeAnyMotionDown();
7966}
7967
7968TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
7969 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007970 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7971 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007972 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7973
7974 touch();
7975
7976 mTouchWindow->consumeAnyMotionDown();
7977}
7978
7979TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
7980 const sp<FakeWindowHandle>& w =
7981 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
7982 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7983
7984 touch();
7985
7986 mTouchWindow->consumeAnyMotionDown();
7987}
7988
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00007989TEST_F(InputDispatcherUntrustedTouchesTest,
7990 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
7991 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
7992 const sp<FakeWindowHandle>& w =
7993 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
7994 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7995
7996 touch();
7997
7998 mTouchWindow->assertNoEvents();
7999}
8000
8001TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8002 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8003 const sp<FakeWindowHandle>& w =
8004 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
8005 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8006
8007 touch();
8008
8009 mTouchWindow->consumeAnyMotionDown();
8010}
8011
8012TEST_F(InputDispatcherUntrustedTouchesTest,
8013 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8014 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8015 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008016 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8017 OPACITY_ABOVE_THRESHOLD);
8018 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8019
8020 touch();
8021
8022 mTouchWindow->consumeAnyMotionDown();
8023}
8024
8025TEST_F(InputDispatcherUntrustedTouchesTest,
8026 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8027 const sp<FakeWindowHandle>& w1 =
8028 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8029 OPACITY_BELOW_THRESHOLD);
8030 const sp<FakeWindowHandle>& w2 =
8031 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8032 OPACITY_BELOW_THRESHOLD);
8033 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8034
8035 touch();
8036
8037 mTouchWindow->assertNoEvents();
8038}
8039
8040/**
8041 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8042 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8043 * (which alone would result in allowing touches) does not affect the blocking behavior.
8044 */
8045TEST_F(InputDispatcherUntrustedTouchesTest,
8046 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8047 const sp<FakeWindowHandle>& wB =
8048 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8049 OPACITY_BELOW_THRESHOLD);
8050 const sp<FakeWindowHandle>& wC =
8051 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8052 OPACITY_BELOW_THRESHOLD);
8053 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8054
8055 touch();
8056
8057 mTouchWindow->assertNoEvents();
8058}
8059
8060/**
8061 * This test is testing that a window from a different UID but with same application token doesn't
8062 * block the touch. Apps can share the application token for close UI collaboration for example.
8063 */
8064TEST_F(InputDispatcherUntrustedTouchesTest,
8065 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8066 const sp<FakeWindowHandle>& w =
8067 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8068 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008069 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8070
8071 touch();
8072
8073 mTouchWindow->consumeAnyMotionDown();
8074}
8075
arthurhungb89ccb02020-12-30 16:19:01 +08008076class InputDispatcherDragTests : public InputDispatcherTest {
8077protected:
8078 std::shared_ptr<FakeApplicationHandle> mApp;
8079 sp<FakeWindowHandle> mWindow;
8080 sp<FakeWindowHandle> mSecondWindow;
8081 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008082 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008083 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8084 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008085
8086 void SetUp() override {
8087 InputDispatcherTest::SetUp();
8088 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008089 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008090 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008091
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008092 mSecondWindow =
8093 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008094 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008095
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008096 mSpyWindow =
8097 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008098 mSpyWindow->setSpy(true);
8099 mSpyWindow->setTrustedOverlay(true);
8100 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8101
arthurhungb89ccb02020-12-30 16:19:01 +08008102 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008103 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008104 }
8105
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008106 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8107 switch (fromSource) {
8108 case AINPUT_SOURCE_TOUCHSCREEN:
8109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8110 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8111 ADISPLAY_ID_DEFAULT, {50, 50}))
8112 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8113 break;
8114 case AINPUT_SOURCE_STYLUS:
8115 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8116 injectMotionEvent(
8117 mDispatcher,
8118 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8119 AINPUT_SOURCE_STYLUS)
8120 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008121 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008122 .x(50)
8123 .y(50))
8124 .build()));
8125 break;
8126 case AINPUT_SOURCE_MOUSE:
8127 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8128 injectMotionEvent(
8129 mDispatcher,
8130 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8131 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8132 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008133 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008134 .x(50)
8135 .y(50))
8136 .build()));
8137 break;
8138 default:
8139 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8140 }
arthurhungb89ccb02020-12-30 16:19:01 +08008141
8142 // Window should receive motion event.
8143 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008144 // Spy window should also receive motion event
8145 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008146 }
8147
8148 // Start performing drag, we will create a drag window and transfer touch to it.
8149 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8150 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008151 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008152 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008153 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008154 }
arthurhungb89ccb02020-12-30 16:19:01 +08008155
8156 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008157 mDragWindow =
8158 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008159 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08008160 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008161 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008162
8163 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008164 bool transferred =
8165 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008166 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008167 if (transferred) {
8168 mWindow->consumeMotionCancel();
8169 mDragWindow->consumeMotionDown();
8170 }
8171 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008172 }
8173};
8174
8175TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008176 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008177
8178 // Move on window.
8179 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8180 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8181 ADISPLAY_ID_DEFAULT, {50, 50}))
8182 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8183 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8184 mWindow->consumeDragEvent(false, 50, 50);
8185 mSecondWindow->assertNoEvents();
8186
8187 // Move to another window.
8188 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8189 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8190 ADISPLAY_ID_DEFAULT, {150, 50}))
8191 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8192 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8193 mWindow->consumeDragEvent(true, 150, 50);
8194 mSecondWindow->consumeDragEvent(false, 50, 50);
8195
8196 // Move back to original window.
8197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8198 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8199 ADISPLAY_ID_DEFAULT, {50, 50}))
8200 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8201 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8202 mWindow->consumeDragEvent(false, 50, 50);
8203 mSecondWindow->consumeDragEvent(true, -50, 50);
8204
8205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8206 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8207 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8208 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8209 mWindow->assertNoEvents();
8210 mSecondWindow->assertNoEvents();
8211}
8212
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008213TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008214 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008215
8216 // No cancel event after drag start
8217 mSpyWindow->assertNoEvents();
8218
8219 const MotionEvent secondFingerDownEvent =
8220 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8221 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008222 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8223 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008224 .build();
8225 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8226 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8227 InputEventInjectionSync::WAIT_FOR_RESULT))
8228 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8229
8230 // Receives cancel for first pointer after next pointer down
8231 mSpyWindow->consumeMotionCancel();
8232 mSpyWindow->consumeMotionDown();
8233
8234 mSpyWindow->assertNoEvents();
8235}
8236
arthurhungf452d0b2021-01-06 00:19:52 +08008237TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008238 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008239
8240 // Move on window.
8241 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8242 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8243 ADISPLAY_ID_DEFAULT, {50, 50}))
8244 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8245 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8246 mWindow->consumeDragEvent(false, 50, 50);
8247 mSecondWindow->assertNoEvents();
8248
8249 // Move to another window.
8250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8251 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8252 ADISPLAY_ID_DEFAULT, {150, 50}))
8253 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8254 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8255 mWindow->consumeDragEvent(true, 150, 50);
8256 mSecondWindow->consumeDragEvent(false, 50, 50);
8257
8258 // drop to another window.
8259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8260 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8261 {150, 50}))
8262 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8263 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8264 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8265 mWindow->assertNoEvents();
8266 mSecondWindow->assertNoEvents();
8267}
8268
arthurhung6d4bed92021-03-17 11:59:33 +08008269TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008270 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008271
8272 // Move on window and keep button pressed.
8273 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8274 injectMotionEvent(mDispatcher,
8275 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8276 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008277 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008278 .build()))
8279 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8280 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8281 mWindow->consumeDragEvent(false, 50, 50);
8282 mSecondWindow->assertNoEvents();
8283
8284 // Move to another window and release button, expect to drop item.
8285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8286 injectMotionEvent(mDispatcher,
8287 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8288 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008289 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008290 .build()))
8291 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8292 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8293 mWindow->assertNoEvents();
8294 mSecondWindow->assertNoEvents();
8295 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8296
8297 // nothing to the window.
8298 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8299 injectMotionEvent(mDispatcher,
8300 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8301 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008302 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008303 .build()))
8304 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8305 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8306 mWindow->assertNoEvents();
8307 mSecondWindow->assertNoEvents();
8308}
8309
Arthur Hung54745652022-04-20 07:17:41 +00008310TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008311 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008312
8313 // Set second window invisible.
8314 mSecondWindow->setVisible(false);
8315 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8316
8317 // Move on window.
8318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8319 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8320 ADISPLAY_ID_DEFAULT, {50, 50}))
8321 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8322 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8323 mWindow->consumeDragEvent(false, 50, 50);
8324 mSecondWindow->assertNoEvents();
8325
8326 // Move to another window.
8327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8328 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8329 ADISPLAY_ID_DEFAULT, {150, 50}))
8330 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8331 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8332 mWindow->consumeDragEvent(true, 150, 50);
8333 mSecondWindow->assertNoEvents();
8334
8335 // drop to another window.
8336 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8337 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8338 {150, 50}))
8339 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8340 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8341 mFakePolicy->assertDropTargetEquals(nullptr);
8342 mWindow->assertNoEvents();
8343 mSecondWindow->assertNoEvents();
8344}
8345
Arthur Hung54745652022-04-20 07:17:41 +00008346TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008347 // Ensure window could track pointerIds if it didn't support split touch.
8348 mWindow->setPreventSplitting(true);
8349
Arthur Hung54745652022-04-20 07:17:41 +00008350 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8351 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8352 {50, 50}))
8353 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8354 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8355
8356 const MotionEvent secondFingerDownEvent =
8357 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8358 .displayId(ADISPLAY_ID_DEFAULT)
8359 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008360 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8361 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008362 .build();
8363 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8364 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8365 InputEventInjectionSync::WAIT_FOR_RESULT))
8366 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008367 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008368
8369 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008370 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008371}
8372
8373TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8374 // First down on second window.
8375 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8376 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8377 {150, 50}))
8378 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8379
8380 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8381
8382 // Second down on first window.
8383 const MotionEvent secondFingerDownEvent =
8384 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8385 .displayId(ADISPLAY_ID_DEFAULT)
8386 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008387 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8388 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008389 .build();
8390 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8391 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8392 InputEventInjectionSync::WAIT_FOR_RESULT))
8393 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8394 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8395
8396 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008397 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008398
8399 // Move on window.
8400 const MotionEvent secondFingerMoveEvent =
8401 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8402 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008403 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8404 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008405 .build();
8406 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8407 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8408 InputEventInjectionSync::WAIT_FOR_RESULT));
8409 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8410 mWindow->consumeDragEvent(false, 50, 50);
8411 mSecondWindow->consumeMotionMove();
8412
8413 // Release the drag pointer should perform drop.
8414 const MotionEvent secondFingerUpEvent =
8415 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8416 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008417 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8418 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008419 .build();
8420 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8421 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8422 InputEventInjectionSync::WAIT_FOR_RESULT));
8423 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8424 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
8425 mWindow->assertNoEvents();
8426 mSecondWindow->consumeMotionMove();
8427}
8428
Arthur Hung3915c1f2022-05-31 07:17:17 +00008429TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008430 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008431
8432 // Update window of second display.
8433 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008434 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008435 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8436
8437 // Let second display has a touch state.
8438 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8439 injectMotionEvent(mDispatcher,
8440 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8441 AINPUT_SOURCE_TOUCHSCREEN)
8442 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008443 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008444 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008445 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008446 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008447 // Update window again.
8448 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8449
8450 // Move on window.
8451 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8452 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8453 ADISPLAY_ID_DEFAULT, {50, 50}))
8454 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8455 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8456 mWindow->consumeDragEvent(false, 50, 50);
8457 mSecondWindow->assertNoEvents();
8458
8459 // Move to another window.
8460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8461 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8462 ADISPLAY_ID_DEFAULT, {150, 50}))
8463 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8464 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8465 mWindow->consumeDragEvent(true, 150, 50);
8466 mSecondWindow->consumeDragEvent(false, 50, 50);
8467
8468 // drop to another window.
8469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8470 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8471 {150, 50}))
8472 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8473 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8474 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8475 mWindow->assertNoEvents();
8476 mSecondWindow->assertNoEvents();
8477}
8478
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008479TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8480 startDrag(true, AINPUT_SOURCE_MOUSE);
8481 // Move on window.
8482 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8483 injectMotionEvent(mDispatcher,
8484 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8485 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8486 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008487 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008488 .x(50)
8489 .y(50))
8490 .build()))
8491 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8492 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8493 mWindow->consumeDragEvent(false, 50, 50);
8494 mSecondWindow->assertNoEvents();
8495
8496 // Move to another window.
8497 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8498 injectMotionEvent(mDispatcher,
8499 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8500 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8501 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008502 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008503 .x(150)
8504 .y(50))
8505 .build()))
8506 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8507 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8508 mWindow->consumeDragEvent(true, 150, 50);
8509 mSecondWindow->consumeDragEvent(false, 50, 50);
8510
8511 // drop to another window.
8512 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8513 injectMotionEvent(mDispatcher,
8514 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8515 .buttonState(0)
8516 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008517 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008518 .x(150)
8519 .y(50))
8520 .build()))
8521 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8522 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8523 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8524 mWindow->assertNoEvents();
8525 mSecondWindow->assertNoEvents();
8526}
8527
Vishnu Nair062a8672021-09-03 16:07:44 -07008528class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8529
8530TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8531 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->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008535 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8536 window->setFocusable(true);
8537 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8538 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008539 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008540
8541 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008542 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008543 window->assertNoEvents();
8544
Prabir Pradhan678438e2023-04-13 19:32:51 +00008545 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8546 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008547 window->assertNoEvents();
8548
8549 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008550 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008551 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8552
Prabir Pradhan678438e2023-04-13 19:32:51 +00008553 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008554 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8555
Prabir Pradhan678438e2023-04-13 19:32:51 +00008556 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8557 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008558 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8559 window->assertNoEvents();
8560}
8561
8562TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8563 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8564 std::make_shared<FakeApplicationHandle>();
8565 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008566 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8567 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008568 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8569 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008570 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008571 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008572 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8573 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008574 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008575 window->setOwnerInfo(222, 222);
8576 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8577 window->setFocusable(true);
8578 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8579 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008580 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008581
8582 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008583 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008584 window->assertNoEvents();
8585
Prabir Pradhan678438e2023-04-13 19:32:51 +00008586 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8587 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008588 window->assertNoEvents();
8589
8590 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008591 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008592 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
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, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8600 window->assertNoEvents();
8601}
8602
8603TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8604 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8605 std::make_shared<FakeApplicationHandle>();
8606 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008607 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8608 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008609 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8610 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008611 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008612 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008613 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8614 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008615 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008616 window->setOwnerInfo(222, 222);
8617 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8618 window->setFocusable(true);
8619 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8620 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008621 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008622
8623 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008624 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008625 window->assertNoEvents();
8626
Prabir Pradhan678438e2023-04-13 19:32:51 +00008627 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8628 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008629 window->assertNoEvents();
8630
8631 // When the window is no longer obscured because it went on top, it should get input
8632 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8633
Prabir Pradhan678438e2023-04-13 19:32:51 +00008634 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008635 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8636
Prabir Pradhan678438e2023-04-13 19:32:51 +00008637 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8638 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008639 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8640 window->assertNoEvents();
8641}
8642
Antonio Kantekf16f2832021-09-28 04:39:20 +00008643class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8644protected:
8645 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008646 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008647 sp<FakeWindowHandle> mWindow;
8648 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008649 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008650
8651 void SetUp() override {
8652 InputDispatcherTest::SetUp();
8653
8654 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008655 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008656 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008657 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008658 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008659 mSecondWindow =
8660 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008661 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008662 mThirdWindow =
8663 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8664 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8665 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008666
8667 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008668 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8669 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8670 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008671 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008672
Antonio Kantek15beb512022-06-13 22:35:41 +00008673 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008674 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008675 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008676 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8677 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008678 mThirdWindow->assertNoEvents();
8679 }
8680
8681 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8682 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008683 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008684 SECOND_DISPLAY_ID)) {
8685 mWindow->assertNoEvents();
8686 mSecondWindow->assertNoEvents();
8687 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008688 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008689 }
8690
Antonio Kantek15beb512022-06-13 22:35:41 +00008691 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid,
8692 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008693 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8694 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008695 mWindow->consumeTouchModeEvent(inTouchMode);
8696 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008697 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008698 }
8699};
8700
Antonio Kantek26defcf2022-02-08 01:12:27 +00008701TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008702 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008703 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8704 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008705 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008706}
8707
Antonio Kantek26defcf2022-02-08 01:12:27 +00008708TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8709 const WindowInfo& windowInfo = *mWindow->getInfo();
8710 int32_t ownerPid = windowInfo.ownerPid;
8711 int32_t ownerUid = windowInfo.ownerUid;
8712 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
8713 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008714 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008715 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008716 mWindow->assertNoEvents();
8717 mSecondWindow->assertNoEvents();
8718}
8719
8720TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8721 const WindowInfo& windowInfo = *mWindow->getInfo();
8722 int32_t ownerPid = windowInfo.ownerPid;
8723 int32_t ownerUid = windowInfo.ownerUid;
8724 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
Antonio Kantek15beb512022-06-13 22:35:41 +00008725 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008726 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008727}
8728
Antonio Kantekf16f2832021-09-28 04:39:20 +00008729TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008730 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008731 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8732 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008733 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008734 mWindow->assertNoEvents();
8735 mSecondWindow->assertNoEvents();
8736}
8737
Antonio Kantek15beb512022-06-13 22:35:41 +00008738TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8739 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8740 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8741 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008742 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008743 mWindow->assertNoEvents();
8744 mSecondWindow->assertNoEvents();
8745 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8746}
8747
Antonio Kantek48710e42022-03-24 14:19:30 -07008748TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8749 // Interact with the window first.
8750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8751 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8752 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8753
8754 // Then remove focus.
8755 mWindow->setFocusable(false);
8756 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8757
8758 // Assert that caller can switch touch mode by owning one of the last interacted window.
8759 const WindowInfo& windowInfo = *mWindow->getInfo();
8760 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8761 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008762 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008763}
8764
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008765class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8766public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008767 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008768 std::shared_ptr<FakeApplicationHandle> application =
8769 std::make_shared<FakeApplicationHandle>();
8770 std::string name = "Fake Spy ";
8771 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008772 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8773 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008774 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008775 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008776 return spy;
8777 }
8778
8779 sp<FakeWindowHandle> createForeground() {
8780 std::shared_ptr<FakeApplicationHandle> application =
8781 std::make_shared<FakeApplicationHandle>();
8782 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008783 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8784 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008785 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008786 return window;
8787 }
8788
8789private:
8790 int mSpyCount{0};
8791};
8792
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008793using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008794/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008795 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8796 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008797TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8798 ScopedSilentDeath _silentDeath;
8799
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008800 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008801 spy->setTrustedOverlay(false);
8802 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8803 ".* not a trusted overlay");
8804}
8805
8806/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008807 * Input injection into a display with a spy window but no foreground windows should succeed.
8808 */
8809TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008810 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008811 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
8812
8813 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8814 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8815 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8816 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8817}
8818
8819/**
8820 * Verify the order in which different input windows receive events. The touched foreground window
8821 * (if there is one) should always receive the event first. When there are multiple spy windows, the
8822 * spy windows will receive the event according to their Z-order, where the top-most spy window will
8823 * receive events before ones belows it.
8824 *
8825 * Here, we set up a scenario with four windows in the following Z order from the top:
8826 * spy1, spy2, window, spy3.
8827 * We then inject an event and verify that the foreground "window" receives it first, followed by
8828 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
8829 * window.
8830 */
8831TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
8832 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008833 auto spy1 = createSpy();
8834 auto spy2 = createSpy();
8835 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008836 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
8837 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
8838 const size_t numChannels = channels.size();
8839
Michael Wright8e9a8562022-02-09 13:44:29 +00008840 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008841 if (!epollFd.ok()) {
8842 FAIL() << "Failed to create epoll fd";
8843 }
8844
8845 for (size_t i = 0; i < numChannels; i++) {
8846 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
8847 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
8848 FAIL() << "Failed to add fd to epoll";
8849 }
8850 }
8851
8852 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8853 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8854 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8855
8856 std::vector<size_t> eventOrder;
8857 std::vector<struct epoll_event> events(numChannels);
8858 for (;;) {
8859 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
8860 (100ms).count());
8861 if (nFds < 0) {
8862 FAIL() << "Failed to call epoll_wait";
8863 }
8864 if (nFds == 0) {
8865 break; // epoll_wait timed out
8866 }
8867 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07008868 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07008869 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008870 channels[i]->consumeMotionDown();
8871 }
8872 }
8873
8874 // Verify the order in which the events were received.
8875 EXPECT_EQ(3u, eventOrder.size());
8876 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
8877 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
8878 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
8879}
8880
8881/**
8882 * A spy window using the NOT_TOUCHABLE flag does not receive events.
8883 */
8884TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
8885 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008886 auto spy = createSpy();
8887 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008888 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8889
8890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8891 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8892 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8893 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8894 spy->assertNoEvents();
8895}
8896
8897/**
8898 * A spy window will only receive gestures that originate within its touchable region. Gestures that
8899 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
8900 * to the window.
8901 */
8902TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
8903 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008904 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008905 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
8906 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8907
8908 // Inject an event outside the spy window's touchable region.
8909 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8910 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8911 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8912 window->consumeMotionDown();
8913 spy->assertNoEvents();
8914 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8915 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8916 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8917 window->consumeMotionUp();
8918 spy->assertNoEvents();
8919
8920 // Inject an event inside the spy window's touchable region.
8921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8922 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8923 {5, 10}))
8924 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8925 window->consumeMotionDown();
8926 spy->consumeMotionDown();
8927}
8928
8929/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008930 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008931 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008932 */
8933TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
8934 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008935 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008936 auto spy = createSpy();
8937 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008938 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008939 spy->setFrame(Rect{0, 0, 20, 20});
8940 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8941
8942 // Inject an event outside the spy window's frame and touchable region.
8943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008944 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8945 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008946 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8947 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008948 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008949}
8950
8951/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008952 * Even when a spy window spans over multiple foreground windows, the spy should receive all
8953 * pointers that are down within its bounds.
8954 */
8955TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
8956 auto windowLeft = createForeground();
8957 windowLeft->setFrame({0, 0, 100, 200});
8958 auto windowRight = createForeground();
8959 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008960 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008961 spy->setFrame({0, 0, 200, 200});
8962 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
8963
8964 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8965 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8966 {50, 50}))
8967 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8968 windowLeft->consumeMotionDown();
8969 spy->consumeMotionDown();
8970
8971 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008972 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008973 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008974 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8975 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008976 .build();
8977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8978 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8979 InputEventInjectionSync::WAIT_FOR_RESULT))
8980 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8981 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00008982 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008983}
8984
8985/**
8986 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
8987 * the spy should receive the second pointer with ACTION_DOWN.
8988 */
8989TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
8990 auto window = createForeground();
8991 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008992 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008993 spyRight->setFrame({100, 0, 200, 200});
8994 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
8995
8996 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8997 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8998 {50, 50}))
8999 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9000 window->consumeMotionDown();
9001 spyRight->assertNoEvents();
9002
9003 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009004 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009005 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009006 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9007 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009008 .build();
9009 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9010 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9011 InputEventInjectionSync::WAIT_FOR_RESULT))
9012 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009013 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009014 spyRight->consumeMotionDown();
9015}
9016
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009017/**
9018 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9019 * windows should be allowed to control split touch.
9020 */
9021TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009022 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009023 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009024 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009025 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009026
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009027 auto window = createForeground();
9028 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009029
9030 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9031
9032 // First finger down, no window touched.
9033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9034 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9035 {100, 200}))
9036 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9037 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9038 window->assertNoEvents();
9039
9040 // Second finger down on window, the window should receive touch down.
9041 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009042 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009043 .displayId(ADISPLAY_ID_DEFAULT)
9044 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009045 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9046 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009047 .build();
9048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9049 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9050 InputEventInjectionSync::WAIT_FOR_RESULT))
9051 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9052
9053 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009054 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009055}
9056
9057/**
9058 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9059 * do not receive key events.
9060 */
9061TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009062 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009063 spy->setFocusable(false);
9064
9065 auto window = createForeground();
9066 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9067 setFocusedWindow(window);
9068 window->consumeFocusEvent(true);
9069
9070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
9071 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9072 window->consumeKeyDown(ADISPLAY_ID_NONE);
9073
9074 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
9075 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9076 window->consumeKeyUp(ADISPLAY_ID_NONE);
9077
9078 spy->assertNoEvents();
9079}
9080
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009081using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9082
9083/**
9084 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9085 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9086 */
9087TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9088 auto window = createForeground();
9089 auto spy1 = createSpy();
9090 auto spy2 = createSpy();
9091 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
9092
9093 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9094 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9095 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9096 window->consumeMotionDown();
9097 spy1->consumeMotionDown();
9098 spy2->consumeMotionDown();
9099
9100 // Pilfer pointers from the second spy window.
9101 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9102 spy2->assertNoEvents();
9103 spy1->consumeMotionCancel();
9104 window->consumeMotionCancel();
9105
9106 // The rest of the gesture should only be sent to the second spy window.
9107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9108 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9109 ADISPLAY_ID_DEFAULT))
9110 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9111 spy2->consumeMotionMove();
9112 spy1->assertNoEvents();
9113 window->assertNoEvents();
9114}
9115
9116/**
9117 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9118 * in the middle of the gesture.
9119 */
9120TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9121 auto window = createForeground();
9122 auto spy = createSpy();
9123 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9124
9125 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9126 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9127 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9128 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9129 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9130
9131 window->releaseChannel();
9132
9133 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9134
9135 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9136 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9137 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9138 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9139}
9140
9141/**
9142 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9143 * the spy, but not to any other windows.
9144 */
9145TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9146 auto spy = createSpy();
9147 auto window = createForeground();
9148
9149 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9150
9151 // First finger down on the window and the spy.
9152 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9153 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9154 {100, 200}))
9155 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9156 spy->consumeMotionDown();
9157 window->consumeMotionDown();
9158
9159 // Spy window pilfers the pointers.
9160 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9161 window->consumeMotionCancel();
9162
9163 // Second finger down on the window and spy, but the window should not receive the pointer down.
9164 const MotionEvent secondFingerDownEvent =
9165 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9166 .displayId(ADISPLAY_ID_DEFAULT)
9167 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009168 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9169 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009170 .build();
9171 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9172 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9173 InputEventInjectionSync::WAIT_FOR_RESULT))
9174 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9175
Harry Cutts33476232023-01-30 19:57:29 +00009176 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009177
9178 // Third finger goes down outside all windows, so injection should fail.
9179 const MotionEvent thirdFingerDownEvent =
9180 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9181 .displayId(ADISPLAY_ID_DEFAULT)
9182 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009183 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9184 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9185 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009186 .build();
9187 ASSERT_EQ(InputEventInjectionResult::FAILED,
9188 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9189 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009190 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009191
9192 spy->assertNoEvents();
9193 window->assertNoEvents();
9194}
9195
9196/**
9197 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9198 */
9199TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9200 auto spy = createSpy();
9201 spy->setFrame(Rect(0, 0, 100, 100));
9202 auto window = createForeground();
9203 window->setFrame(Rect(0, 0, 200, 200));
9204
9205 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9206
9207 // First finger down on the window only
9208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9209 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9210 {150, 150}))
9211 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9212 window->consumeMotionDown();
9213
9214 // Second finger down on the spy and window
9215 const MotionEvent secondFingerDownEvent =
9216 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9217 .displayId(ADISPLAY_ID_DEFAULT)
9218 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009219 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9220 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009221 .build();
9222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9223 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9224 InputEventInjectionSync::WAIT_FOR_RESULT))
9225 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9226 spy->consumeMotionDown();
9227 window->consumeMotionPointerDown(1);
9228
9229 // Third finger down on the spy and window
9230 const MotionEvent thirdFingerDownEvent =
9231 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9232 .displayId(ADISPLAY_ID_DEFAULT)
9233 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009234 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9235 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9236 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009237 .build();
9238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9239 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9240 InputEventInjectionSync::WAIT_FOR_RESULT))
9241 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9242 spy->consumeMotionPointerDown(1);
9243 window->consumeMotionPointerDown(2);
9244
9245 // Spy window pilfers the pointers.
9246 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9247 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9248 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9249
9250 spy->assertNoEvents();
9251 window->assertNoEvents();
9252}
9253
9254/**
9255 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9256 * other windows should be canceled. If this results in the cancellation of all pointers for some
9257 * window, then that window should receive ACTION_CANCEL.
9258 */
9259TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9260 auto spy = createSpy();
9261 spy->setFrame(Rect(0, 0, 100, 100));
9262 auto window = createForeground();
9263 window->setFrame(Rect(0, 0, 200, 200));
9264
9265 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9266
9267 // First finger down on both spy and window
9268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9269 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9270 {10, 10}))
9271 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9272 window->consumeMotionDown();
9273 spy->consumeMotionDown();
9274
9275 // Second finger down on the spy and window
9276 const MotionEvent secondFingerDownEvent =
9277 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9278 .displayId(ADISPLAY_ID_DEFAULT)
9279 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009280 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9281 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009282 .build();
9283 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9284 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9285 InputEventInjectionSync::WAIT_FOR_RESULT))
9286 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9287 spy->consumeMotionPointerDown(1);
9288 window->consumeMotionPointerDown(1);
9289
9290 // Spy window pilfers the pointers.
9291 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9292 window->consumeMotionCancel();
9293
9294 spy->assertNoEvents();
9295 window->assertNoEvents();
9296}
9297
9298/**
9299 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9300 * be sent to other windows
9301 */
9302TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9303 auto spy = createSpy();
9304 spy->setFrame(Rect(0, 0, 100, 100));
9305 auto window = createForeground();
9306 window->setFrame(Rect(0, 0, 200, 200));
9307
9308 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9309
9310 // First finger down on both window and spy
9311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9312 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9313 {10, 10}))
9314 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9315 window->consumeMotionDown();
9316 spy->consumeMotionDown();
9317
9318 // Spy window pilfers the pointers.
9319 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9320 window->consumeMotionCancel();
9321
9322 // Second finger down on the window only
9323 const MotionEvent secondFingerDownEvent =
9324 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9325 .displayId(ADISPLAY_ID_DEFAULT)
9326 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009327 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9328 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009329 .build();
9330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9331 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9332 InputEventInjectionSync::WAIT_FOR_RESULT))
9333 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9334 window->consumeMotionDown();
9335 window->assertNoEvents();
9336
9337 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9338 spy->consumeMotionMove();
9339 spy->assertNoEvents();
9340}
9341
Prabir Pradhand65552b2021-10-07 11:23:50 -07009342class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9343public:
9344 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9345 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9346 std::make_shared<FakeApplicationHandle>();
9347 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009348 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9349 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009350 overlay->setFocusable(false);
9351 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009352 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009353 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009354 overlay->setTrustedOverlay(true);
9355
9356 std::shared_ptr<FakeApplicationHandle> application =
9357 std::make_shared<FakeApplicationHandle>();
9358 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009359 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9360 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009361 window->setFocusable(true);
9362 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009363
9364 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9365 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9366 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009367 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009368 return {std::move(overlay), std::move(window)};
9369 }
9370
9371 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009372 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009373 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009374 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009375 }
9376
9377 void sendStylusEvent(int32_t action) {
9378 NotifyMotionArgs motionArgs =
9379 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9380 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009381 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009382 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009383 }
9384};
9385
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009386using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9387
9388TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
9389 ScopedSilentDeath _silentDeath;
9390
Prabir Pradhand65552b2021-10-07 11:23:50 -07009391 auto [overlay, window] = setupStylusOverlayScenario();
9392 overlay->setTrustedOverlay(false);
9393 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9394 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9395 ".* not a trusted overlay");
9396}
9397
9398TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9399 auto [overlay, window] = setupStylusOverlayScenario();
9400 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9401
9402 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9403 overlay->consumeMotionDown();
9404 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9405 overlay->consumeMotionUp();
9406
9407 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9408 window->consumeMotionDown();
9409 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9410 window->consumeMotionUp();
9411
9412 overlay->assertNoEvents();
9413 window->assertNoEvents();
9414}
9415
9416TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9417 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009418 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009419 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9420
9421 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9422 overlay->consumeMotionDown();
9423 window->consumeMotionDown();
9424 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9425 overlay->consumeMotionUp();
9426 window->consumeMotionUp();
9427
9428 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9429 window->consumeMotionDown();
9430 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9431 window->consumeMotionUp();
9432
9433 overlay->assertNoEvents();
9434 window->assertNoEvents();
9435}
9436
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009437/**
9438 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9439 * The scenario is as follows:
9440 * - The stylus interceptor overlay is configured as a spy window.
9441 * - The stylus interceptor spy receives the start of a new stylus gesture.
9442 * - It pilfers pointers and then configures itself to no longer be a spy.
9443 * - The stylus interceptor continues to receive the rest of the gesture.
9444 */
9445TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9446 auto [overlay, window] = setupStylusOverlayScenario();
9447 overlay->setSpy(true);
9448 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9449
9450 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9451 overlay->consumeMotionDown();
9452 window->consumeMotionDown();
9453
9454 // The interceptor pilfers the pointers.
9455 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9456 window->consumeMotionCancel();
9457
9458 // The interceptor configures itself so that it is no longer a spy.
9459 overlay->setSpy(false);
9460 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9461
9462 // It continues to receive the rest of the stylus gesture.
9463 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9464 overlay->consumeMotionMove();
9465 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9466 overlay->consumeMotionUp();
9467
9468 window->assertNoEvents();
9469}
9470
Prabir Pradhan5735a322022-04-11 17:23:34 +00009471struct User {
9472 int32_t mPid;
9473 int32_t mUid;
9474 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9475 std::unique_ptr<InputDispatcher>& mDispatcher;
9476
9477 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
9478 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9479
9480 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9481 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9482 ADISPLAY_ID_DEFAULT, {100, 200},
9483 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9484 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9485 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9486 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9487 }
9488
9489 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009490 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009491 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009492 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009493 mPolicyFlags);
9494 }
9495
9496 sp<FakeWindowHandle> createWindow() const {
9497 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9498 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009499 sp<FakeWindowHandle> window =
9500 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9501 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009502 window->setOwnerInfo(mPid, mUid);
9503 return window;
9504 }
9505};
9506
9507using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9508
9509TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
9510 auto owner = User(mDispatcher, 10, 11);
9511 auto window = owner.createWindow();
9512 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9513
9514 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9515 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9516 window->consumeMotionDown();
9517
9518 setFocusedWindow(window);
9519 window->consumeFocusEvent(true);
9520
9521 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9522 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9523 window->consumeKeyDown(ADISPLAY_ID_NONE);
9524}
9525
9526TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
9527 auto owner = User(mDispatcher, 10, 11);
9528 auto window = owner.createWindow();
9529 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9530
9531 auto rando = User(mDispatcher, 20, 21);
9532 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9533 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9534
9535 setFocusedWindow(window);
9536 window->consumeFocusEvent(true);
9537
9538 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9539 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9540 window->assertNoEvents();
9541}
9542
9543TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
9544 auto owner = User(mDispatcher, 10, 11);
9545 auto window = owner.createWindow();
9546 auto spy = owner.createWindow();
9547 spy->setSpy(true);
9548 spy->setTrustedOverlay(true);
9549 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9550
9551 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9552 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9553 spy->consumeMotionDown();
9554 window->consumeMotionDown();
9555}
9556
9557TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
9558 auto owner = User(mDispatcher, 10, 11);
9559 auto window = owner.createWindow();
9560
9561 auto rando = User(mDispatcher, 20, 21);
9562 auto randosSpy = rando.createWindow();
9563 randosSpy->setSpy(true);
9564 randosSpy->setTrustedOverlay(true);
9565 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9566
9567 // The event is targeted at owner's window, so injection should succeed, but the spy should
9568 // not receive the event.
9569 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9570 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9571 randosSpy->assertNoEvents();
9572 window->consumeMotionDown();
9573}
9574
9575TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
9576 auto owner = User(mDispatcher, 10, 11);
9577 auto window = owner.createWindow();
9578
9579 auto rando = User(mDispatcher, 20, 21);
9580 auto randosSpy = rando.createWindow();
9581 randosSpy->setSpy(true);
9582 randosSpy->setTrustedOverlay(true);
9583 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9584
9585 // A user that has injection permission can inject into any window.
9586 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9587 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9588 ADISPLAY_ID_DEFAULT));
9589 randosSpy->consumeMotionDown();
9590 window->consumeMotionDown();
9591
9592 setFocusedWindow(randosSpy);
9593 randosSpy->consumeFocusEvent(true);
9594
9595 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9596 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9597 window->assertNoEvents();
9598}
9599
9600TEST_F(InputDispatcherTargetedInjectionTest, CanGenerateActionOutsideToOtherUids) {
9601 auto owner = User(mDispatcher, 10, 11);
9602 auto window = owner.createWindow();
9603
9604 auto rando = User(mDispatcher, 20, 21);
9605 auto randosWindow = rando.createWindow();
9606 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9607 randosWindow->setWatchOutsideTouch(true);
9608 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9609
9610 // We allow generation of ACTION_OUTSIDE events into windows owned by different uids.
9611 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9612 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9613 window->consumeMotionDown();
9614 randosWindow->consumeMotionOutside();
9615}
9616
Garfield Tane84e6f92019-08-29 17:28:41 -07009617} // namespace android::inputdispatcher