blob: 905331cc951a94f724934afdb2f4ae84c2ba11c1 [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"
Prabir Pradhan9205e422023-05-16 20:06:13 +000018#include "EventBuilders.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080019
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070020#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080021#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080022#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070023#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070024#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000025#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080026#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080027#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100028#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080029#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080030#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100031
Garfield Tan1c7bc862020-01-28 13:24:04 -080032#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080033#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070034#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080035#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080036#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080037
Garfield Tan1c7bc862020-01-28 13:24:04 -080038using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050039using android::gui::FocusRequest;
40using android::gui::TouchOcclusionMode;
41using android::gui::WindowInfo;
42using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080043using android::os::InputEventInjectionResult;
44using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080045
Garfield Tane84e6f92019-08-29 17:28:41 -070046namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080047
Dominik Laskowski2f01d772022-03-23 16:01:29 -070048using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080049using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070050
Michael Wrightd02c5b62014-02-10 15:10:22 -080051// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000052static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080053
54// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000055static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080056static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080057
Jeff Brownf086ddb2014-02-11 14:28:48 -080058// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000059static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
60static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080061
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080062static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
63static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
64static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
65static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070066static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080067static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080068static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080069static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080070/**
71 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
72 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
73 * index 0) is the new pointer going down. The same pointer could have been placed at a different
74 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
75 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
76 * pointer id=0 leaves but the pointer id=1 remains.
77 */
78static constexpr int32_t POINTER_0_DOWN =
79 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080080static constexpr int32_t POINTER_1_DOWN =
81 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000082static constexpr int32_t POINTER_2_DOWN =
83 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000084static constexpr int32_t POINTER_3_DOWN =
85 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000086static constexpr int32_t POINTER_0_UP =
87 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080088static constexpr int32_t POINTER_1_UP =
89 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +000090static constexpr int32_t POINTER_2_UP =
91 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080092
Antonio Kantek15beb512022-06-13 22:35:41 +000093// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhan5735a322022-04-11 17:23:34 +000094static constexpr int32_t WINDOW_PID = 999;
95static constexpr int32_t WINDOW_UID = 1001;
96
Antonio Kantek15beb512022-06-13 22:35:41 +000097// The default pid and uid for the windows created on the secondary display by the test.
98static constexpr int32_t SECONDARY_WINDOW_PID = 1010;
99static constexpr int32_t SECONDARY_WINDOW_UID = 1012;
100
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
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700849namespace {
850
Arthur Hungb92218b2018-08-14 12:00:21 +0800851// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700852static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700853// Default input dispatching timeout if there is no focused application or paused window
854// from which to determine an appropriate dispatching timeout.
855static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
856 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
857 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800858
859class FakeApplicationHandle : public InputApplicationHandle {
860public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700861 FakeApplicationHandle() {
862 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700863 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500864 mInfo.dispatchingTimeoutMillis =
865 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700866 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800867 virtual ~FakeApplicationHandle() {}
868
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000869 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700870
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500871 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
872 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700873 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800874};
875
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800876class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800877public:
Garfield Tan15601662020-09-22 15:32:38 -0700878 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800879 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700880 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800881 }
882
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800883 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700884 InputEvent* event;
885 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
886 if (!consumeSeq) {
887 return nullptr;
888 }
889 finishEvent(*consumeSeq);
890 return event;
891 }
892
893 /**
894 * Receive an event without acknowledging it.
895 * Return the sequence number that could later be used to send finished signal.
896 */
897 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800898 uint32_t consumeSeq;
899 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800900
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800901 std::chrono::time_point start = std::chrono::steady_clock::now();
902 status_t status = WOULD_BLOCK;
903 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000904 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800905 &event);
906 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
907 if (elapsed > 100ms) {
908 break;
909 }
910 }
911
912 if (status == WOULD_BLOCK) {
913 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700914 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800915 }
916
917 if (status != OK) {
918 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700919 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800920 }
921 if (event == nullptr) {
922 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700923 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800924 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700925 if (outEvent != nullptr) {
926 *outEvent = event;
927 }
928 return consumeSeq;
929 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800930
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700931 /**
932 * To be used together with "receiveEvent" to complete the consumption of an event.
933 */
934 void finishEvent(uint32_t consumeSeq) {
935 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
936 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800937 }
938
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000939 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
940 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
941 ASSERT_EQ(OK, status);
942 }
943
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700944 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000945 std::optional<int32_t> expectedDisplayId,
946 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800947 InputEvent* event = consume();
948
949 ASSERT_NE(nullptr, event) << mName.c_str()
950 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800951 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700952 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
953 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800954
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000955 if (expectedDisplayId.has_value()) {
956 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
957 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800958
Tiger Huang8664f8c2018-10-11 19:14:35 +0800959 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700960 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800961 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
962 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000963 if (expectedFlags.has_value()) {
964 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
965 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800966 break;
967 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700968 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800969 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000970 assertMotionAction(expectedAction, motionEvent.getAction());
971
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000972 if (expectedFlags.has_value()) {
973 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
974 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800975 break;
976 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700977 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100978 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
979 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700980 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800981 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
982 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700983 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000984 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
985 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700986 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800987 FAIL() << "Use 'consumeDragEvent' for DRAG events";
988 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800989 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800990 }
991
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800992 MotionEvent* consumeMotion() {
993 InputEvent* event = consume();
994
995 if (event == nullptr) {
996 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
997 return nullptr;
998 }
999
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001000 if (event->getType() != InputEventType::MOTION) {
1001 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001002 return nullptr;
1003 }
1004 return static_cast<MotionEvent*>(event);
1005 }
1006
1007 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1008 MotionEvent* motionEvent = consumeMotion();
1009 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1010 ASSERT_THAT(*motionEvent, matcher);
1011 }
1012
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001013 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1014 InputEvent* event = consume();
1015 ASSERT_NE(nullptr, event) << mName.c_str()
1016 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001017 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1018 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001019
1020 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1021 << mName.c_str() << ": event displayId should always be NONE.";
1022
1023 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1024 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001025 }
1026
Prabir Pradhan99987712020-11-10 18:43:05 -08001027 void consumeCaptureEvent(bool hasCapture) {
1028 const InputEvent* event = consume();
1029 ASSERT_NE(nullptr, event) << mName.c_str()
1030 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001031 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1032 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001033
1034 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1035 << mName.c_str() << ": event displayId should always be NONE.";
1036
1037 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1038 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1039 }
1040
arthurhungb89ccb02020-12-30 16:19:01 +08001041 void consumeDragEvent(bool isExiting, float x, float y) {
1042 const InputEvent* event = consume();
1043 ASSERT_NE(nullptr, event) << mName.c_str()
1044 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001045 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001046
1047 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1048 << mName.c_str() << ": event displayId should always be NONE.";
1049
1050 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1051 EXPECT_EQ(isExiting, dragEvent.isExiting());
1052 EXPECT_EQ(x, dragEvent.getX());
1053 EXPECT_EQ(y, dragEvent.getY());
1054 }
1055
Antonio Kantekf16f2832021-09-28 04:39:20 +00001056 void consumeTouchModeEvent(bool inTouchMode) {
1057 const InputEvent* event = consume();
1058 ASSERT_NE(nullptr, event) << mName.c_str()
1059 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001060 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1061 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001062
1063 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1064 << mName.c_str() << ": event displayId should always be NONE.";
1065 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1066 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1067 }
1068
chaviwd1c23182019-12-20 18:44:56 -08001069 void assertNoEvents() {
1070 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001071 if (event == nullptr) {
1072 return;
1073 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001074 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001075 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1076 ADD_FAILURE() << "Received key event "
1077 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001078 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001079 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1080 ADD_FAILURE() << "Received motion event "
1081 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001082 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001083 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1084 ADD_FAILURE() << "Received focus event, hasFocus = "
1085 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001086 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001087 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1088 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1089 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001090 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001091 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1092 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1093 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001094 }
1095 FAIL() << mName.c_str()
1096 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001097 }
1098
1099 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1100
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001101 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1102
chaviwd1c23182019-12-20 18:44:56 -08001103protected:
1104 std::unique_ptr<InputConsumer> mConsumer;
1105 PreallocatedInputEventFactory mEventFactory;
1106
1107 std::string mName;
1108};
1109
chaviw3277faf2021-05-19 16:45:23 -05001110class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001111public:
1112 static const int32_t WIDTH = 600;
1113 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001114
Chris Yea209fde2020-07-22 13:54:51 -07001115 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001116 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001117 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001118 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001119 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001120 base::Result<std::unique_ptr<InputChannel>> channel =
1121 dispatcher->createInputChannel(name);
1122 token = (*channel)->getConnectionToken();
1123 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001124 }
1125
1126 inputApplicationHandle->updateInfo();
1127 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1128
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001129 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001130 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001131 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001132 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001133 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001134 mInfo.frameLeft = 0;
1135 mInfo.frameTop = 0;
1136 mInfo.frameRight = WIDTH;
1137 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001138 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001139 mInfo.globalScaleFactor = 1.0;
1140 mInfo.touchableRegion.clear();
1141 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001142 mInfo.ownerPid = WINDOW_PID;
1143 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001144 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001145 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001146 }
1147
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001148 sp<FakeWindowHandle> clone(int32_t displayId) {
1149 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1150 handle->mInfo = mInfo;
1151 handle->mInfo.displayId = displayId;
1152 handle->mInfo.id = sId++;
1153 handle->mInputReceiver = mInputReceiver;
1154 return handle;
1155 }
1156
1157 /**
1158 * This is different from clone, because clone will make a "mirror" window - a window with the
1159 * same token, but a different ID. The original window and the clone window are allowed to be
1160 * sent to the dispatcher at the same time - they can coexist inside the dispatcher.
1161 * This function will create a different object of WindowInfoHandle, but with the same
1162 * properties as the original object - including the ID.
1163 * You can use either the old or the new object to consume the events.
1164 * IMPORTANT: The duplicated object is supposed to replace the original object, and not appear
1165 * at the same time inside dispatcher.
1166 */
1167 sp<FakeWindowHandle> duplicate() {
1168 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mName);
1169 handle->mInfo = mInfo;
1170 handle->mInputReceiver = mInputReceiver;
Arthur Hungabbb9d82021-09-01 14:52:30 +00001171 return handle;
1172 }
1173
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001174 void setTouchable(bool touchable) {
1175 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1176 }
chaviwd1c23182019-12-20 18:44:56 -08001177
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001178 void setFocusable(bool focusable) {
1179 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1180 }
1181
1182 void setVisible(bool visible) {
1183 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1184 }
Vishnu Nair958da932020-08-21 17:12:37 -07001185
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001186 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001187 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001188 }
1189
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001190 void setPaused(bool paused) {
1191 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1192 }
1193
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001194 void setPreventSplitting(bool preventSplitting) {
1195 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001196 }
1197
1198 void setSlippery(bool slippery) {
1199 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1200 }
1201
1202 void setWatchOutsideTouch(bool watchOutside) {
1203 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1204 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001205
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001206 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1207
1208 void setInterceptsStylus(bool interceptsStylus) {
1209 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1210 }
1211
1212 void setDropInput(bool dropInput) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1214 }
1215
1216 void setDropInputIfObscured(bool dropInputIfObscured) {
1217 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1218 }
1219
1220 void setNoInputChannel(bool noInputChannel) {
1221 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1222 }
1223
Josep del Riob3981622023-04-18 15:49:45 +00001224 void setDisableUserActivity(bool disableUserActivity) {
1225 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1226 }
1227
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001228 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1229
chaviw3277faf2021-05-19 16:45:23 -05001230 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001231
Bernardo Rufino7393d172021-02-26 13:56:11 +00001232 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1233
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001234 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001235 mInfo.frameLeft = frame.left;
1236 mInfo.frameTop = frame.top;
1237 mInfo.frameRight = frame.right;
1238 mInfo.frameBottom = frame.bottom;
1239 mInfo.touchableRegion.clear();
1240 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001241
1242 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1243 ui::Transform translate;
1244 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1245 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001246 }
1247
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001248 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1249
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001250 void setIsWallpaper(bool isWallpaper) {
1251 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1252 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001253
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001254 void setDupTouchToWallpaper(bool hasWallpaper) {
1255 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1256 }
chaviwd1c23182019-12-20 18:44:56 -08001257
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001258 void setTrustedOverlay(bool trustedOverlay) {
1259 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1260 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001261
chaviw9eaa22c2020-07-01 16:21:27 -07001262 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1263 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1264 }
1265
1266 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001267
yunho.shinf4a80b82020-11-16 21:13:57 +09001268 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1269
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001270 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001271 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001272 }
1273
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001274 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001275 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001276 }
1277
Svet Ganov5d3bc372020-01-26 23:11:07 -08001278 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001279 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001280 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1281 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001282 }
1283
1284 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001285 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001286 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1287 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001288 }
1289
1290 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001291 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001292 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1293 }
1294
1295 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1296 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001297 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001298 expectedFlags);
1299 }
1300
Svet Ganov5d3bc372020-01-26 23:11:07 -08001301 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001302 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1303 int32_t expectedFlags = 0) {
1304 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1305 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001306 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001307 }
1308
1309 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001310 int32_t expectedFlags = 0) {
1311 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1312 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001313 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001314 }
1315
1316 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001317 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001318 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001319 expectedFlags);
1320 }
1321
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001322 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1323 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001324 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001325 expectedFlags);
1326 }
1327
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001328 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1329 int32_t expectedFlags = 0) {
1330 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001331 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001332 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001333 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1334 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1335 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1336 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1337 }
1338
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001339 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1340 ASSERT_NE(mInputReceiver, nullptr)
1341 << "Cannot consume events from a window with no receiver";
1342 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1343 }
1344
Prabir Pradhan99987712020-11-10 18:43:05 -08001345 void consumeCaptureEvent(bool hasCapture) {
1346 ASSERT_NE(mInputReceiver, nullptr)
1347 << "Cannot consume events from a window with no receiver";
1348 mInputReceiver->consumeCaptureEvent(hasCapture);
1349 }
1350
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001351 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1352 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001353 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001354 ASSERT_THAT(*motionEvent, matcher);
1355 }
1356
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001357 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001358 std::optional<int32_t> expectedDisplayId,
1359 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001360 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1361 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1362 expectedFlags);
1363 }
1364
arthurhungb89ccb02020-12-30 16:19:01 +08001365 void consumeDragEvent(bool isExiting, float x, float y) {
1366 mInputReceiver->consumeDragEvent(isExiting, x, y);
1367 }
1368
Antonio Kantekf16f2832021-09-28 04:39:20 +00001369 void consumeTouchModeEvent(bool inTouchMode) {
1370 ASSERT_NE(mInputReceiver, nullptr)
1371 << "Cannot consume events from a window with no receiver";
1372 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1373 }
1374
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001375 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001376 if (mInputReceiver == nullptr) {
1377 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1378 return std::nullopt;
1379 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001380 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001381 }
1382
1383 void finishEvent(uint32_t sequenceNum) {
1384 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1385 mInputReceiver->finishEvent(sequenceNum);
1386 }
1387
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001388 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1389 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1390 mInputReceiver->sendTimeline(inputEventId, timeline);
1391 }
1392
chaviwaf87b3e2019-10-01 16:59:28 -07001393 InputEvent* consume() {
1394 if (mInputReceiver == nullptr) {
1395 return nullptr;
1396 }
1397 return mInputReceiver->consume();
1398 }
1399
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001400 MotionEvent* consumeMotion() {
1401 InputEvent* event = consume();
1402 if (event == nullptr) {
1403 ADD_FAILURE() << "Consume failed : no event";
1404 return nullptr;
1405 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001406 if (event->getType() != InputEventType::MOTION) {
1407 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001408 return nullptr;
1409 }
1410 return static_cast<MotionEvent*>(event);
1411 }
1412
Arthur Hungb92218b2018-08-14 12:00:21 +08001413 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001414 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001415 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001416 return; // Can't receive events if the window does not have input channel
1417 }
1418 ASSERT_NE(nullptr, mInputReceiver)
1419 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001420 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001421 }
1422
chaviwaf87b3e2019-10-01 16:59:28 -07001423 sp<IBinder> getToken() { return mInfo.token; }
1424
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001425 const std::string& getName() { return mName; }
1426
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001427 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1428 mInfo.ownerPid = ownerPid;
1429 mInfo.ownerUid = ownerUid;
1430 }
1431
Prabir Pradhanedd96402022-02-15 01:46:16 -08001432 int32_t getPid() const { return mInfo.ownerPid; }
1433
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001434 void destroyReceiver() { mInputReceiver = nullptr; }
1435
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001436 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1437
chaviwd1c23182019-12-20 18:44:56 -08001438private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001439 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001440 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001441 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001442 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001443 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001444};
1445
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001446std::atomic<int32_t> FakeWindowHandle::sId{1};
1447
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001448static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001449 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001450 int32_t displayId = ADISPLAY_ID_NONE,
1451 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001452 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001453 bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
1454 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001455 KeyEvent event;
1456 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1457
1458 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001459 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001460 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1461 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001462
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001463 if (!allowKeyRepeat) {
1464 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1465 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001466 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001467 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001468}
1469
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001470static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001471 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001472 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001473}
1474
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001475// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1476// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1477// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001478static InputEventInjectionResult injectKeyDownNoRepeat(
1479 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001480 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001481 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001482 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001483}
1484
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001485static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001486 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001487 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001488}
1489
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001490static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001491 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001492 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001493 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1494 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
1495 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1496 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001497}
1498
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001499static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001500 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001501 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001502 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001503 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1504 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001505 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001506 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
1507 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001508 MotionEventBuilder motionBuilder =
1509 MotionEventBuilder(action, source)
1510 .displayId(displayId)
1511 .eventTime(eventTime)
1512 .rawXCursorPosition(cursorPosition.x)
1513 .rawYCursorPosition(cursorPosition.y)
1514 .pointer(
1515 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1516 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1517 motionBuilder.downTime(eventTime);
1518 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001519
1520 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001521 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1522 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001523}
1524
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001525static InputEventInjectionResult injectMotionDown(
1526 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1527 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001528 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001529}
1530
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001531static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001532 int32_t source, int32_t displayId,
1533 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001534 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001535}
1536
Jackal Guof9696682018-10-05 12:23:23 +08001537static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1538 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1539 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001540 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001541 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1542 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001543
1544 return args;
1545}
1546
Josep del Riob3981622023-04-18 15:49:45 +00001547static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1548 int32_t displayId = ADISPLAY_ID_NONE) {
1549 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1550 // Define a valid key event.
1551 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1552 displayId, 0, action, /* flags */ 0, AKEYCODE_C, KEY_C, AMETA_META_ON,
1553 currentTime);
1554
1555 return args;
1556}
1557
1558static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1559 int32_t displayId = ADISPLAY_ID_NONE) {
1560 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1561 // Define a valid key event.
1562 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1563 displayId, 0, action, /* flags */ 0, AKEYCODE_ASSIST, KEY_ASSISTANT,
1564 AMETA_NONE, currentTime);
1565
1566 return args;
1567}
1568
Prabir Pradhan678438e2023-04-13 19:32:51 +00001569[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1570 int32_t displayId,
1571 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001572 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001573 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1574 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1575 }
1576
chaviwd1c23182019-12-20 18:44:56 -08001577 PointerProperties pointerProperties[pointerCount];
1578 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001579
chaviwd1c23182019-12-20 18:44:56 -08001580 for (size_t i = 0; i < pointerCount; i++) {
1581 pointerProperties[i].clear();
1582 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001583 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001584
chaviwd1c23182019-12-20 18:44:56 -08001585 pointerCoords[i].clear();
1586 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1587 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1588 }
Jackal Guof9696682018-10-05 12:23:23 +08001589
1590 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1591 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001592 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001593 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1594 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001595 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1596 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001597 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1598 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001599
1600 return args;
1601}
1602
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001603static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1604 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1605}
1606
chaviwd1c23182019-12-20 18:44:56 -08001607static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1608 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1609}
1610
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001611static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1612 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001613 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001614}
1615
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001616} // namespace
1617
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001618/**
1619 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1620 * broken channel.
1621 */
1622TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1623 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1624 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001625 sp<FakeWindowHandle>::make(application, mDispatcher,
1626 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001627
1628 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1629
1630 // Window closes its channel, but the window remains.
1631 window->destroyReceiver();
1632 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1633}
1634
Arthur Hungb92218b2018-08-14 12:00:21 +08001635TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001636 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001637 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1638 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001639
Arthur Hung72d8dc32020-03-28 00:48:39 +00001640 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1642 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1643 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001644
1645 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001646 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001647}
1648
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001649TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1650 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001651 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1652 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001653
1654 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1655 // Inject a MotionEvent to an unknown display.
1656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1657 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1658 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1659
1660 // Window should receive motion event.
1661 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1662}
1663
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001664/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001665 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001666 * This test serves as a sanity check for the next test, where setInputWindows is
1667 * called twice.
1668 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001669TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001670 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001671 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1672 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001673 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001674
1675 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001677 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1678 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001679 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001680
1681 // Window should receive motion event.
1682 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1683}
1684
1685/**
1686 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001687 */
1688TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001689 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001690 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1691 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001692 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001693
1694 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1695 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001697 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1698 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001699 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001700
1701 // Window should receive motion event.
1702 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1703}
1704
Arthur Hungb92218b2018-08-14 12:00:21 +08001705// The foreground window should receive the first touch down event.
1706TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001707 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001708 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001709 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001710 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001711 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001712
Arthur Hung72d8dc32020-03-28 00:48:39 +00001713 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1715 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1716 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001717
1718 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001719 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001720 windowSecond->assertNoEvents();
1721}
1722
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001723/**
1724 * Two windows: A top window, and a wallpaper behind the window.
1725 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1726 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001727 * 1. foregroundWindow <-- dup touch to wallpaper
1728 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001729 */
1730TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1732 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001733 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001734 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001735 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001736 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001737 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001738
1739 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1740 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1741 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1742 {100, 200}))
1743 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1744
1745 // Both foreground window and its wallpaper should receive the touch down
1746 foregroundWindow->consumeMotionDown();
1747 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1748
1749 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1750 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1751 ADISPLAY_ID_DEFAULT, {110, 200}))
1752 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1753
1754 foregroundWindow->consumeMotionMove();
1755 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1756
1757 // Now the foreground window goes away, but the wallpaper stays
1758 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1759 foregroundWindow->consumeMotionCancel();
1760 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1761 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1762}
1763
1764/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001765 * Two fingers down on the window, and lift off the first finger.
1766 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1767 * contains a single pointer.
1768 */
1769TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1770 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1771 sp<FakeWindowHandle> window =
1772 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1773
1774 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001775 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001776 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1777 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1778 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001779 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001780 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1781 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1782 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1783 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001784 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001785 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1786 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1787 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1788 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001789 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1790 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1791 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1792
1793 // Remove the window. The gesture should be canceled
1794 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
1795 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1796 window->consumeMotionEvent(
1797 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1798}
1799
1800/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001801 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1802 * with the following differences:
1803 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1804 * clean up the connection.
1805 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1806 * Ensure that there's no crash in the dispatcher.
1807 */
1808TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1809 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1810 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001811 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001812 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001813 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001814 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001815 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001816
1817 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1818 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1819 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1820 {100, 200}))
1821 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1822
1823 // Both foreground window and its wallpaper should receive the touch down
1824 foregroundWindow->consumeMotionDown();
1825 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1826
1827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1828 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1829 ADISPLAY_ID_DEFAULT, {110, 200}))
1830 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1831
1832 foregroundWindow->consumeMotionMove();
1833 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1834
1835 // Wallpaper closes its channel, but the window remains.
1836 wallpaperWindow->destroyReceiver();
1837 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1838
1839 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1840 // is no longer valid.
1841 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1842 foregroundWindow->consumeMotionCancel();
1843}
1844
Arthur Hungc539dbb2022-12-08 07:45:36 +00001845class ShouldSplitTouchFixture : public InputDispatcherTest,
1846 public ::testing::WithParamInterface<bool> {};
1847INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1848 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001849/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001850 * A single window that receives touch (on top), and a wallpaper window underneath it.
1851 * The top window gets a multitouch gesture.
1852 * Ensure that wallpaper gets the same gesture.
1853 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001854TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001855 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001856 sp<FakeWindowHandle> foregroundWindow =
1857 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1858 foregroundWindow->setDupTouchToWallpaper(true);
1859 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001860
1861 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001862 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001863 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001864
Arthur Hungc539dbb2022-12-08 07:45:36 +00001865 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001866
1867 // Touch down on top window
1868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1869 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1870 {100, 100}))
1871 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1872
1873 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001874 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001875 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1876
1877 // Second finger down on the top window
1878 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001879 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001880 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001881 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1882 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001883 .build();
1884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1885 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1886 InputEventInjectionSync::WAIT_FOR_RESULT))
1887 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1888
Harry Cutts33476232023-01-30 19:57:29 +00001889 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1890 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001891 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001892
1893 const MotionEvent secondFingerUpEvent =
1894 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1895 .displayId(ADISPLAY_ID_DEFAULT)
1896 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001897 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1898 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001899 .build();
1900 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1901 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
1902 InputEventInjectionSync::WAIT_FOR_RESULT))
1903 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1904 foregroundWindow->consumeMotionPointerUp(0);
1905 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1906
1907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001908 injectMotionEvent(mDispatcher,
1909 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1910 AINPUT_SOURCE_TOUCHSCREEN)
1911 .displayId(ADISPLAY_ID_DEFAULT)
1912 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1913 .pointer(PointerBuilder(/* id */ 1,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001914 ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001915 .x(100)
1916 .y(100))
1917 .build(),
1918 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001919 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1920 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1921 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001922}
1923
1924/**
1925 * Two windows: a window on the left and window on the right.
1926 * A third window, wallpaper, is behind both windows, and spans both top windows.
1927 * The first touch down goes to the left window. A second pointer touches down on the right window.
1928 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1929 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1930 * ACTION_POINTER_DOWN(1).
1931 */
1932TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1933 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1934 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001935 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001936 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001937 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001938
1939 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001940 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001941 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001942 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001943
1944 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001945 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001946 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001947 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001948
1949 mDispatcher->setInputWindows(
1950 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1951
1952 // Touch down on left window
1953 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1954 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1955 {100, 100}))
1956 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1957
1958 // Both foreground window and its wallpaper should receive the touch down
1959 leftWindow->consumeMotionDown();
1960 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1961
1962 // Second finger down on the right window
1963 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001964 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001965 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001966 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1967 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001968 .build();
1969 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1970 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1971 InputEventInjectionSync::WAIT_FOR_RESULT))
1972 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1973
1974 leftWindow->consumeMotionMove();
1975 // Since the touch is split, right window gets ACTION_DOWN
1976 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001977 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001978 expectedWallpaperFlags);
1979
1980 // Now, leftWindow, which received the first finger, disappears.
1981 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
1982 leftWindow->consumeMotionCancel();
1983 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1984 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1985
1986 // The pointer that's still down on the right window moves, and goes to the right window only.
1987 // As far as the dispatcher's concerned though, both pointers are still present.
1988 const MotionEvent secondFingerMoveEvent =
1989 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1990 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001991 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1992 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001993 .build();
1994 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1995 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
1996 InputEventInjectionSync::WAIT_FOR_RESULT));
1997 rightWindow->consumeMotionMove();
1998
1999 leftWindow->assertNoEvents();
2000 rightWindow->assertNoEvents();
2001 wallpaperWindow->assertNoEvents();
2002}
2003
Arthur Hungc539dbb2022-12-08 07:45:36 +00002004/**
2005 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2006 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2007 * The right window should receive ACTION_DOWN.
2008 */
2009TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002010 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002011 sp<FakeWindowHandle> leftWindow =
2012 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2013 leftWindow->setFrame(Rect(0, 0, 200, 200));
2014 leftWindow->setDupTouchToWallpaper(true);
2015 leftWindow->setSlippery(true);
2016
2017 sp<FakeWindowHandle> rightWindow =
2018 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2019 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002020
2021 sp<FakeWindowHandle> wallpaperWindow =
2022 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2023 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002024
Arthur Hungc539dbb2022-12-08 07:45:36 +00002025 mDispatcher->setInputWindows(
2026 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002027
Arthur Hungc539dbb2022-12-08 07:45:36 +00002028 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2030 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002031 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002032 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002033
2034 // Both foreground window and its wallpaper should receive the touch down
2035 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002036 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2037
Arthur Hungc539dbb2022-12-08 07:45:36 +00002038 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002040 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2041 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002042 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2043
Arthur Hungc539dbb2022-12-08 07:45:36 +00002044 leftWindow->consumeMotionCancel();
2045 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2046 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002047}
2048
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002049/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002050 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2051 * interactive, it might stop sending this flag.
2052 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2053 * to have a consistent input stream.
2054 *
2055 * Test procedure:
2056 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2057 * DOWN (new gesture).
2058 *
2059 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2060 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2061 *
2062 * We technically just need a single window here, but we are using two windows (spy on top and a
2063 * regular window below) to emulate the actual situation where it happens on the device.
2064 */
2065TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2066 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2067 sp<FakeWindowHandle> spyWindow =
2068 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2069 spyWindow->setFrame(Rect(0, 0, 200, 200));
2070 spyWindow->setTrustedOverlay(true);
2071 spyWindow->setSpy(true);
2072
2073 sp<FakeWindowHandle> window =
2074 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2075 window->setFrame(Rect(0, 0, 200, 200));
2076
2077 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2078 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002079
2080 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002081 mDispatcher->notifyMotion(
2082 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2083 .deviceId(touchDeviceId)
2084 .policyFlags(DEFAULT_POLICY_FLAGS)
2085 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2086 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002087
Prabir Pradhan678438e2023-04-13 19:32:51 +00002088 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2089 .deviceId(touchDeviceId)
2090 .policyFlags(DEFAULT_POLICY_FLAGS)
2091 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2092 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2093 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002094 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2095 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2096 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2097 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2098
2099 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002100 mDispatcher->notifyMotion(
2101 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2102 .deviceId(touchDeviceId)
2103 .policyFlags(0)
2104 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2105 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2106 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002107 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2108 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2109
2110 // We don't need to reset the device to reproduce the issue, but the reset event typically
2111 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002112 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002113
2114 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002115 mDispatcher->notifyMotion(
2116 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2117 .deviceId(touchDeviceId)
2118 .policyFlags(DEFAULT_POLICY_FLAGS)
2119 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2120 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002121 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2122 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2123
2124 // No more events
2125 spyWindow->assertNoEvents();
2126 window->assertNoEvents();
2127}
2128
2129/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002130 * Two windows: a window on the left and a window on the right.
2131 * Mouse is hovered from the right window into the left window.
2132 * Next, we tap on the left window, where the cursor was last seen.
2133 * The second tap is done onto the right window.
2134 * The mouse and tap are from two different devices.
2135 * We technically don't need to set the downtime / eventtime for these events, but setting these
2136 * explicitly helps during debugging.
2137 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2138 * In the buggy implementation, a tap on the right window would cause a crash.
2139 */
2140TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2141 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2142 sp<FakeWindowHandle> leftWindow =
2143 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2144 leftWindow->setFrame(Rect(0, 0, 200, 200));
2145
2146 sp<FakeWindowHandle> rightWindow =
2147 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2148 rightWindow->setFrame(Rect(200, 0, 400, 200));
2149
2150 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2151 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2152 // stale.
2153 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2154 const int32_t mouseDeviceId = 6;
2155 const int32_t touchDeviceId = 4;
2156 // Move the cursor from right
2157 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2158 injectMotionEvent(mDispatcher,
2159 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2160 AINPUT_SOURCE_MOUSE)
2161 .deviceId(mouseDeviceId)
2162 .downTime(baseTime + 10)
2163 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002164 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002165 .x(300)
2166 .y(100))
2167 .build()));
2168 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2169
2170 // .. to the left window
2171 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2172 injectMotionEvent(mDispatcher,
2173 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2174 AINPUT_SOURCE_MOUSE)
2175 .deviceId(mouseDeviceId)
2176 .downTime(baseTime + 10)
2177 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002178 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002179 .x(110)
2180 .y(100))
2181 .build()));
2182 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2183 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2184 // Now tap the left window
2185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2186 injectMotionEvent(mDispatcher,
2187 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2188 AINPUT_SOURCE_TOUCHSCREEN)
2189 .deviceId(touchDeviceId)
2190 .downTime(baseTime + 40)
2191 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002192 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002193 .x(100)
2194 .y(100))
2195 .build()));
2196 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2197 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2198
2199 // release tap
2200 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2201 injectMotionEvent(mDispatcher,
2202 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2203 AINPUT_SOURCE_TOUCHSCREEN)
2204 .deviceId(touchDeviceId)
2205 .downTime(baseTime + 40)
2206 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002207 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002208 .x(100)
2209 .y(100))
2210 .build()));
2211 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2212
2213 // Tap the window on the right
2214 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2215 injectMotionEvent(mDispatcher,
2216 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2217 AINPUT_SOURCE_TOUCHSCREEN)
2218 .deviceId(touchDeviceId)
2219 .downTime(baseTime + 60)
2220 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002221 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002222 .x(300)
2223 .y(100))
2224 .build()));
2225 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2226
2227 // release tap
2228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2229 injectMotionEvent(mDispatcher,
2230 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2231 AINPUT_SOURCE_TOUCHSCREEN)
2232 .deviceId(touchDeviceId)
2233 .downTime(baseTime + 60)
2234 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002235 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002236 .x(300)
2237 .y(100))
2238 .build()));
2239 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2240
2241 // No more events
2242 leftWindow->assertNoEvents();
2243 rightWindow->assertNoEvents();
2244}
2245
2246/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002247 * Start hovering in a window. While this hover is still active, make another window appear on top.
2248 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2249 * While the top window is present, the hovering is stopped.
2250 * Later, hovering gets resumed again.
2251 * Ensure that new hover gesture is handled correctly.
2252 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2253 * to the window that's currently being hovered over.
2254 */
2255TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2256 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2257 sp<FakeWindowHandle> window =
2258 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2259 window->setFrame(Rect(0, 0, 200, 200));
2260
2261 // Only a single window is present at first
2262 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2263
2264 // Start hovering in the window
2265 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2266 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2267 .build());
2268 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2269
2270 // Now, an obscuring window appears!
2271 sp<FakeWindowHandle> obscuringWindow =
2272 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2273 ADISPLAY_ID_DEFAULT,
2274 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2275 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2276 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2277 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2278 obscuringWindow->setNoInputChannel(true);
2279 obscuringWindow->setFocusable(false);
2280 obscuringWindow->setAlpha(1.0);
2281 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2282
2283 // While this new obscuring window is present, the hovering is stopped
2284 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2285 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2286 .build());
2287 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2288
2289 // Now the obscuring window goes away.
2290 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2291
2292 // And a new hover gesture starts.
2293 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2294 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2295 .build());
2296 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2297}
2298
2299/**
2300 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2301 * the obscuring window.
2302 */
2303TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2304 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2305 sp<FakeWindowHandle> window =
2306 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2307 window->setFrame(Rect(0, 0, 200, 200));
2308
2309 // Only a single window is present at first
2310 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2311
2312 // Start hovering in the window
2313 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2314 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2315 .build());
2316 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2317
2318 // Now, an obscuring window appears!
2319 sp<FakeWindowHandle> obscuringWindow =
2320 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2321 ADISPLAY_ID_DEFAULT,
2322 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2323 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2324 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2325 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2326 obscuringWindow->setNoInputChannel(true);
2327 obscuringWindow->setFocusable(false);
2328 obscuringWindow->setAlpha(1.0);
2329 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2330
2331 // While this new obscuring window is present, the hovering continues. The event can't go to the
2332 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2333 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2334 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2335 .build());
2336 obscuringWindow->assertNoEvents();
2337 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2338
2339 // Now the obscuring window goes away.
2340 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2341
2342 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2343 // so it should generate a HOVER_ENTER
2344 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2345 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2346 .build());
2347 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2348
2349 // Now the MOVE should be getting dispatched normally
2350 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2351 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2352 .build());
2353 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2354}
2355
2356/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002357 * Two windows: a window on the left and a window on the right.
2358 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2359 * down. Then, on the left window, also place second touch pointer down.
2360 * This test tries to reproduce a crash.
2361 * In the buggy implementation, second pointer down on the left window would cause a crash.
2362 */
2363TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2365 sp<FakeWindowHandle> leftWindow =
2366 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2367 leftWindow->setFrame(Rect(0, 0, 200, 200));
2368
2369 sp<FakeWindowHandle> rightWindow =
2370 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2371 rightWindow->setFrame(Rect(200, 0, 400, 200));
2372
2373 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2374
2375 const int32_t touchDeviceId = 4;
2376 const int32_t mouseDeviceId = 6;
2377 NotifyMotionArgs args;
2378
2379 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002380 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2381 .deviceId(mouseDeviceId)
2382 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2383 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002384 leftWindow->consumeMotionEvent(
2385 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2386
2387 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002388 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2389 .deviceId(mouseDeviceId)
2390 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2391 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2392 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002393
2394 leftWindow->consumeMotionEvent(
2395 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2396 leftWindow->consumeMotionEvent(
2397 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2398
Prabir Pradhan678438e2023-04-13 19:32:51 +00002399 mDispatcher->notifyMotion(
2400 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2401 .deviceId(mouseDeviceId)
2402 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2403 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2404 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2405 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002406 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2407
2408 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002409 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2410 .deviceId(touchDeviceId)
2411 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2412 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002413 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2414
2415 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2416
2417 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002418 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2419 .deviceId(touchDeviceId)
2420 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2421 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2422 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002423 leftWindow->consumeMotionEvent(
2424 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2425 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2426 // current implementation.
2427 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2428 rightWindow->consumeMotionEvent(
2429 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2430
2431 leftWindow->assertNoEvents();
2432 rightWindow->assertNoEvents();
2433}
2434
2435/**
2436 * On a single window, use two different devices: mouse and touch.
2437 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2438 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2439 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2440 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2441 * represent a new gesture.
2442 */
2443TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2444 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2445 sp<FakeWindowHandle> window =
2446 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2447 window->setFrame(Rect(0, 0, 400, 400));
2448
2449 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2450
2451 const int32_t touchDeviceId = 4;
2452 const int32_t mouseDeviceId = 6;
2453 NotifyMotionArgs args;
2454
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002455 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002456 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2457 .deviceId(touchDeviceId)
2458 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2459 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002460 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002461 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2462 .deviceId(touchDeviceId)
2463 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2464 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2465 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002466 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002467 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2468 .deviceId(touchDeviceId)
2469 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2470 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2471 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002472 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2473 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2474 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2475
2476 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002477 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2478 .deviceId(mouseDeviceId)
2479 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2480 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2481 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002482
2483 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002484 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002485 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2486
Prabir Pradhan678438e2023-04-13 19:32:51 +00002487 mDispatcher->notifyMotion(
2488 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2489 .deviceId(mouseDeviceId)
2490 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2491 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2492 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2493 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002494 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2495
2496 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002497 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2498 .deviceId(touchDeviceId)
2499 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2500 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2501 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002502 // The pointer_down event should be ignored
2503 window->assertNoEvents();
2504}
2505
2506/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002507 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2508 * the injected event.
2509 */
2510TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2511 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2512 sp<FakeWindowHandle> window =
2513 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2514 window->setFrame(Rect(0, 0, 400, 400));
2515
2516 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2517
2518 const int32_t touchDeviceId = 4;
2519 NotifyMotionArgs args;
2520 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2521 // completion.
2522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2523 injectMotionEvent(mDispatcher,
2524 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2525 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002526 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002527 .x(50)
2528 .y(50))
2529 .build()));
2530 window->consumeMotionEvent(
2531 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2532
2533 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2534 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2536 .deviceId(touchDeviceId)
2537 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2538 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002539
2540 window->consumeMotionEvent(
2541 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2542 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2543}
2544
2545/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002546 * This test is similar to the test above, but the sequence of injected events is different.
2547 *
2548 * Two windows: a window on the left and a window on the right.
2549 * Mouse is hovered over the left window.
2550 * Next, we tap on the left window, where the cursor was last seen.
2551 *
2552 * After that, we inject one finger down onto the right window, and then a second finger down onto
2553 * the left window.
2554 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2555 * window (first), and then another on the left window (second).
2556 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2557 * In the buggy implementation, second finger down on the left window would cause a crash.
2558 */
2559TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2560 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2561 sp<FakeWindowHandle> leftWindow =
2562 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2563 leftWindow->setFrame(Rect(0, 0, 200, 200));
2564
2565 sp<FakeWindowHandle> rightWindow =
2566 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2567 rightWindow->setFrame(Rect(200, 0, 400, 200));
2568
2569 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2570
2571 const int32_t mouseDeviceId = 6;
2572 const int32_t touchDeviceId = 4;
2573 // Hover over the left window. Keep the cursor there.
2574 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2575 injectMotionEvent(mDispatcher,
2576 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2577 AINPUT_SOURCE_MOUSE)
2578 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002579 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002580 .x(50)
2581 .y(50))
2582 .build()));
2583 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2584
2585 // Tap on left window
2586 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2587 injectMotionEvent(mDispatcher,
2588 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2589 AINPUT_SOURCE_TOUCHSCREEN)
2590 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002591 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002592 .x(100)
2593 .y(100))
2594 .build()));
2595
2596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2597 injectMotionEvent(mDispatcher,
2598 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2599 AINPUT_SOURCE_TOUCHSCREEN)
2600 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002601 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002602 .x(100)
2603 .y(100))
2604 .build()));
2605 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2606 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2607 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2608
2609 // First finger down on right window
2610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2611 injectMotionEvent(mDispatcher,
2612 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2613 AINPUT_SOURCE_TOUCHSCREEN)
2614 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002615 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002616 .x(300)
2617 .y(100))
2618 .build()));
2619 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2620
2621 // Second finger down on the left window
2622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2623 injectMotionEvent(mDispatcher,
2624 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2625 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002626 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002627 .x(300)
2628 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002629 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002630 .x(100)
2631 .y(100))
2632 .build()));
2633 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2634 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2635
2636 // No more events
2637 leftWindow->assertNoEvents();
2638 rightWindow->assertNoEvents();
2639}
2640
2641/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002642 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2643 * While the touch is down, new hover events from the stylus device should be ignored. After the
2644 * touch is gone, stylus hovering should start working again.
2645 */
2646TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2647 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2648 sp<FakeWindowHandle> window =
2649 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2650 window->setFrame(Rect(0, 0, 200, 200));
2651
2652 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2653
2654 const int32_t stylusDeviceId = 5;
2655 const int32_t touchDeviceId = 4;
2656 // Start hovering with stylus
2657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2658 injectMotionEvent(mDispatcher,
2659 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2660 AINPUT_SOURCE_STYLUS)
2661 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002662 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002663 .x(50)
2664 .y(50))
2665 .build()));
2666 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2667
2668 // Finger down on the window
2669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2670 injectMotionEvent(mDispatcher,
2671 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2672 AINPUT_SOURCE_TOUCHSCREEN)
2673 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002674 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002675 .x(100)
2676 .y(100))
2677 .build()));
2678 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2679 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2680
2681 // Try to continue hovering with stylus. Since we are already down, injection should fail
2682 ASSERT_EQ(InputEventInjectionResult::FAILED,
2683 injectMotionEvent(mDispatcher,
2684 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2685 AINPUT_SOURCE_STYLUS)
2686 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002687 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002688 .x(50)
2689 .y(50))
2690 .build()));
2691 // No event should be sent. This event should be ignored because a pointer from another device
2692 // is already down.
2693
2694 // Lift up the finger
2695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2696 injectMotionEvent(mDispatcher,
2697 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2698 AINPUT_SOURCE_TOUCHSCREEN)
2699 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002700 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002701 .x(100)
2702 .y(100))
2703 .build()));
2704 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2705
2706 // Now that the touch is gone, stylus hovering should start working again
2707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2708 injectMotionEvent(mDispatcher,
2709 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2710 AINPUT_SOURCE_STYLUS)
2711 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002712 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002713 .x(50)
2714 .y(50))
2715 .build()));
2716 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2717 // No more events
2718 window->assertNoEvents();
2719}
2720
2721/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002722 * A spy window above a window with no input channel.
2723 * Start hovering with a stylus device, and then tap with it.
2724 * Ensure spy window receives the entire sequence.
2725 */
2726TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2727 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2728 sp<FakeWindowHandle> spyWindow =
2729 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2730 spyWindow->setFrame(Rect(0, 0, 200, 200));
2731 spyWindow->setTrustedOverlay(true);
2732 spyWindow->setSpy(true);
2733 sp<FakeWindowHandle> window =
2734 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2735 window->setNoInputChannel(true);
2736 window->setFrame(Rect(0, 0, 200, 200));
2737
2738 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2739
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002740 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002741 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2742 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2743 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002744 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2745 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002746 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2747 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2748 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002749 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2750
2751 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002752 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2753 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2754 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002755 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2756
2757 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002758 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2759 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2760 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002761 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2762
2763 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002764 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2765 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2766 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002767 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2768 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002769 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2770 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2771 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002772 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2773
2774 // No more events
2775 spyWindow->assertNoEvents();
2776 window->assertNoEvents();
2777}
2778
2779/**
2780 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2781 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2782 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2783 * While the mouse is down, new move events from the touch device should be ignored.
2784 */
2785TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2786 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2787 sp<FakeWindowHandle> spyWindow =
2788 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2789 spyWindow->setFrame(Rect(0, 0, 200, 200));
2790 spyWindow->setTrustedOverlay(true);
2791 spyWindow->setSpy(true);
2792 sp<FakeWindowHandle> window =
2793 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2794 window->setFrame(Rect(0, 0, 200, 200));
2795
2796 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2797
2798 const int32_t mouseDeviceId = 7;
2799 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002800
2801 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002802 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2803 .deviceId(mouseDeviceId)
2804 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2805 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002806 spyWindow->consumeMotionEvent(
2807 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2808 window->consumeMotionEvent(
2809 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2810
2811 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002812 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2813 .deviceId(touchDeviceId)
2814 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2815 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002816 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2817 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2818 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2819 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2820
Prabir Pradhan678438e2023-04-13 19:32:51 +00002821 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2822 .deviceId(touchDeviceId)
2823 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2824 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002825 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2826 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2827
2828 // Pilfer the stream
2829 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2830 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2831
Prabir Pradhan678438e2023-04-13 19:32:51 +00002832 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2833 .deviceId(touchDeviceId)
2834 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2835 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002836 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2837
2838 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002839 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2840 .deviceId(mouseDeviceId)
2841 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2842 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2843 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002844
2845 spyWindow->consumeMotionEvent(
2846 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2847 spyWindow->consumeMotionEvent(
2848 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2849 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2850
Prabir Pradhan678438e2023-04-13 19:32:51 +00002851 mDispatcher->notifyMotion(
2852 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2853 .deviceId(mouseDeviceId)
2854 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2855 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2856 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2857 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002858 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2859 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2860
2861 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002862 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2863 .deviceId(mouseDeviceId)
2864 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2865 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2866 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002867 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2868 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2869
2870 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002871 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2872 .deviceId(touchDeviceId)
2873 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2874 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002875
2876 // No more events
2877 spyWindow->assertNoEvents();
2878 window->assertNoEvents();
2879}
2880
2881/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002882 * On the display, have a single window, and also an area where there's no window.
2883 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2884 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2885 */
2886TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2887 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2888 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002889 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002890
2891 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002892
2893 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002894 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002895
2896 mDispatcher->waitForIdle();
2897 window->assertNoEvents();
2898
2899 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002900 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002901 mDispatcher->waitForIdle();
2902 window->consumeMotionDown();
2903}
2904
2905/**
2906 * Same test as above, but instead of touching the empty space, the first touch goes to
2907 * non-touchable window.
2908 */
2909TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2910 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2911 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002912 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002913 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2914 window1->setTouchable(false);
2915 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002916 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002917 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2918
2919 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2920
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002921 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002922 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002923
2924 mDispatcher->waitForIdle();
2925 window1->assertNoEvents();
2926 window2->assertNoEvents();
2927
2928 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002929 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002930 mDispatcher->waitForIdle();
2931 window2->consumeMotionDown();
2932}
2933
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002934/**
2935 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2936 * to the event time of the first ACTION_DOWN sent to the particular window.
2937 */
2938TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2939 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2940 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002941 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002942 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2943 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002944 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002945 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2946
2947 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2948
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002949 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002950 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002951
2952 mDispatcher->waitForIdle();
2953 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002954 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002955 window2->assertNoEvents();
2956 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
2957 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
2958 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
2959
2960 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002961 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002962 mDispatcher->waitForIdle();
2963 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002964 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002965 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
2966 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
2967 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
2968 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
2969
2970 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002971 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002972 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002973 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002974
2975 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002976 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002977 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002978 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002979
2980 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
2981 window1->consumeMotionMove();
2982 window1->assertNoEvents();
2983
2984 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002985 mDispatcher->notifyMotion(
2986 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002987 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002988 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002989
Prabir Pradhan678438e2023-04-13 19:32:51 +00002990 mDispatcher->notifyMotion(
2991 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002992 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002993 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002994}
2995
Garfield Tandf26e862020-07-01 20:18:19 -07002996TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07002997 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07002998 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002999 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003000 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003001 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003002 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003003 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003004
3005 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3006
3007 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3008
3009 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003011 injectMotionEvent(mDispatcher,
3012 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3013 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003014 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003015 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003016 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003017
3018 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003020 injectMotionEvent(mDispatcher,
3021 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3022 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003023 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003024 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003025 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3026 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003027
3028 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003030 injectMotionEvent(mDispatcher,
3031 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3032 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003033 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003034 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003035 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3036 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003037
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003039 injectMotionEvent(mDispatcher,
3040 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3041 AINPUT_SOURCE_MOUSE)
3042 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3043 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003044 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003045 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003046 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003047
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003049 injectMotionEvent(mDispatcher,
3050 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3051 AINPUT_SOURCE_MOUSE)
3052 .buttonState(0)
3053 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003054 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003055 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003056 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003057
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003059 injectMotionEvent(mDispatcher,
3060 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3061 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003062 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003063 .build()));
3064 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3065
3066 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003068 injectMotionEvent(mDispatcher,
3069 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3070 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003071 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003072 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003073 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003074
3075 // No more events
3076 windowLeft->assertNoEvents();
3077 windowRight->assertNoEvents();
3078}
3079
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003080/**
3081 * Put two fingers down (and don't release them) and click the mouse button.
3082 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3083 * currently active gesture should be canceled, and the new one should proceed.
3084 */
3085TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3086 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3087 sp<FakeWindowHandle> window =
3088 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3089 window->setFrame(Rect(0, 0, 600, 800));
3090
3091 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3092
3093 const int32_t touchDeviceId = 4;
3094 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003095
3096 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003097 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3098 .deviceId(touchDeviceId)
3099 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3100 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003101
Prabir Pradhan678438e2023-04-13 19:32:51 +00003102 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3103 .deviceId(touchDeviceId)
3104 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3105 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3106 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003107 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3108 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3109
3110 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003111 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3112 .deviceId(mouseDeviceId)
3113 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3114 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3115 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003116 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3117 WithPointerCount(2u)));
3118 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3119
Prabir Pradhan678438e2023-04-13 19:32:51 +00003120 mDispatcher->notifyMotion(
3121 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3122 .deviceId(mouseDeviceId)
3123 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3124 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3125 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3126 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003127 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3128
3129 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3130 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003131 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3132 .deviceId(touchDeviceId)
3133 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3134 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3135 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003136 window->assertNoEvents();
3137}
3138
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003139TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3140 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3141
3142 sp<FakeWindowHandle> spyWindow =
3143 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3144 spyWindow->setFrame(Rect(0, 0, 600, 800));
3145 spyWindow->setTrustedOverlay(true);
3146 spyWindow->setSpy(true);
3147 sp<FakeWindowHandle> window =
3148 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3149 window->setFrame(Rect(0, 0, 600, 800));
3150
3151 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3152 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3153
3154 // Send mouse cursor to the window
3155 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3156 injectMotionEvent(mDispatcher,
3157 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3158 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003159 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003160 .x(100)
3161 .y(100))
3162 .build()));
3163
3164 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3165 WithSource(AINPUT_SOURCE_MOUSE)));
3166 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3167 WithSource(AINPUT_SOURCE_MOUSE)));
3168
3169 window->assertNoEvents();
3170 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003171}
3172
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003173TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3174 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3175
3176 sp<FakeWindowHandle> spyWindow =
3177 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3178 spyWindow->setFrame(Rect(0, 0, 600, 800));
3179 spyWindow->setTrustedOverlay(true);
3180 spyWindow->setSpy(true);
3181 sp<FakeWindowHandle> window =
3182 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3183 window->setFrame(Rect(0, 0, 600, 800));
3184
3185 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3186 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3187
3188 // Send mouse cursor to the window
3189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3190 injectMotionEvent(mDispatcher,
3191 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3192 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003193 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003194 .x(100)
3195 .y(100))
3196 .build()));
3197
3198 // Move mouse cursor
3199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3200 injectMotionEvent(mDispatcher,
3201 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3202 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003203 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003204 .x(110)
3205 .y(110))
3206 .build()));
3207
3208 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3209 WithSource(AINPUT_SOURCE_MOUSE)));
3210 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3211 WithSource(AINPUT_SOURCE_MOUSE)));
3212 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3213 WithSource(AINPUT_SOURCE_MOUSE)));
3214 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3215 WithSource(AINPUT_SOURCE_MOUSE)));
3216 // Touch down on the window
3217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3218 injectMotionEvent(mDispatcher,
3219 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3220 AINPUT_SOURCE_TOUCHSCREEN)
3221 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003222 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003223 .x(200)
3224 .y(200))
3225 .build()));
3226 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3227 WithSource(AINPUT_SOURCE_MOUSE)));
3228 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3229 WithSource(AINPUT_SOURCE_MOUSE)));
3230 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3231 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3232 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3233 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3234
3235 // pilfer the motion, retaining the gesture on the spy window.
3236 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3237 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3238 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3239
3240 // Touch UP on the window
3241 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3242 injectMotionEvent(mDispatcher,
3243 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3244 AINPUT_SOURCE_TOUCHSCREEN)
3245 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003246 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003247 .x(200)
3248 .y(200))
3249 .build()));
3250 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3251 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3252
3253 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3254 // to send a new gesture. It should again go to both windows (spy and the window below), just
3255 // like the first gesture did, before pilfering. The window configuration has not changed.
3256
3257 // One more tap - DOWN
3258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3259 injectMotionEvent(mDispatcher,
3260 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3261 AINPUT_SOURCE_TOUCHSCREEN)
3262 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003263 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003264 .x(250)
3265 .y(250))
3266 .build()));
3267 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3268 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3269 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3270 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3271
3272 // Touch UP on the window
3273 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3274 injectMotionEvent(mDispatcher,
3275 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3276 AINPUT_SOURCE_TOUCHSCREEN)
3277 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003278 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003279 .x(250)
3280 .y(250))
3281 .build()));
3282 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3283 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3284 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3285 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3286
3287 window->assertNoEvents();
3288 spyWindow->assertNoEvents();
3289}
3290
Garfield Tandf26e862020-07-01 20:18:19 -07003291// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3292// directly in this test.
3293TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003294 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003295 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003296 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003297 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003298
3299 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3300
3301 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3302
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003303 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003304 injectMotionEvent(mDispatcher,
3305 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3306 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003307 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003308 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003309 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003310 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003312 injectMotionEvent(mDispatcher,
3313 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3314 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003315 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003316 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003317 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3318 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003319
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003320 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003321 injectMotionEvent(mDispatcher,
3322 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3323 AINPUT_SOURCE_MOUSE)
3324 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3325 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003326 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003327 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003328 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003329
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003331 injectMotionEvent(mDispatcher,
3332 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3333 AINPUT_SOURCE_MOUSE)
3334 .buttonState(0)
3335 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003336 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003337 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003338 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003339
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003341 injectMotionEvent(mDispatcher,
3342 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3343 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003344 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003345 .build()));
3346 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3347
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003348 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3349 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3350 ASSERT_EQ(InputEventInjectionResult::FAILED,
Garfield Tandf26e862020-07-01 20:18:19 -07003351 injectMotionEvent(mDispatcher,
3352 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3353 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003354 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003355 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003356 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003357}
3358
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003359/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003360 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3361 * is generated.
3362 */
3363TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3365 sp<FakeWindowHandle> window =
3366 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3367 window->setFrame(Rect(0, 0, 1200, 800));
3368
3369 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3370
3371 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3372
3373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3374 injectMotionEvent(mDispatcher,
3375 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3376 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003377 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003378 .x(300)
3379 .y(400))
3380 .build()));
3381 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3382
3383 // Remove the window, but keep the channel.
3384 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3385 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3386}
3387
3388/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003389 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3390 */
3391TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3392 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3393 sp<FakeWindowHandle> window =
3394 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3395 window->setFrame(Rect(0, 0, 100, 100));
3396
3397 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3398
3399 const int32_t mouseDeviceId = 7;
3400 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003401
3402 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3404 .deviceId(mouseDeviceId)
3405 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3406 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003407 window->consumeMotionEvent(
3408 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3409
3410 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003411 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3412 .deviceId(touchDeviceId)
3413 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3414 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003415
3416 window->consumeMotionEvent(
3417 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3418 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3419}
3420
3421/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003422 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003423 * The tap causes a HOVER_EXIT event to be generated because the current event
3424 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003425 */
3426TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3427 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3428 sp<FakeWindowHandle> window =
3429 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3430 window->setFrame(Rect(0, 0, 100, 100));
3431
3432 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3433
3434 // Inject a hover_move from mouse.
3435 NotifyMotionArgs motionArgs =
3436 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3437 ADISPLAY_ID_DEFAULT, {{50, 50}});
3438 motionArgs.xCursorPosition = 50;
3439 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003440 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003441 ASSERT_NO_FATAL_FAILURE(
3442 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3443 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003444
3445 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003446 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3447 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3448 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003449 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003450 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3451 WithSource(AINPUT_SOURCE_MOUSE))));
3452
3453 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003454 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3455 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3456
Prabir Pradhan678438e2023-04-13 19:32:51 +00003457 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3458 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003459 ASSERT_NO_FATAL_FAILURE(
3460 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3461 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3462}
3463
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003464TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3465 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3466 sp<FakeWindowHandle> windowDefaultDisplay =
3467 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3468 ADISPLAY_ID_DEFAULT);
3469 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3470 sp<FakeWindowHandle> windowSecondDisplay =
3471 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3472 SECOND_DISPLAY_ID);
3473 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3474
3475 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3476 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3477
3478 // Set cursor position in window in default display and check that hover enter and move
3479 // events are generated.
3480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3481 injectMotionEvent(mDispatcher,
3482 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3483 AINPUT_SOURCE_MOUSE)
3484 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003485 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003486 .x(300)
3487 .y(600))
3488 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003489 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003490
3491 // Remove all windows in secondary display and check that no event happens on window in
3492 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003493 mDispatcher->setInputWindows(
3494 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003495 windowDefaultDisplay->assertNoEvents();
3496
3497 // Move cursor position in window in default display and check that only hover move
3498 // event is generated and not hover enter event.
3499 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3500 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3501 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3502 injectMotionEvent(mDispatcher,
3503 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3504 AINPUT_SOURCE_MOUSE)
3505 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003506 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003507 .x(400)
3508 .y(700))
3509 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003510 windowDefaultDisplay->consumeMotionEvent(
3511 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3512 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003513 windowDefaultDisplay->assertNoEvents();
3514}
3515
Garfield Tan00f511d2019-06-12 16:55:40 -07003516TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003517 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003518
3519 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003520 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003521 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003522 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003523 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003524 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003525
3526 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3527
Arthur Hung72d8dc32020-03-28 00:48:39 +00003528 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003529
3530 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3531 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003533 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003534 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003535 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003536 windowRight->assertNoEvents();
3537}
3538
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003539TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003540 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003541 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3542 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003543 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003544
Arthur Hung72d8dc32020-03-28 00:48:39 +00003545 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003546 setFocusedWindow(window);
3547
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003548 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003549
Prabir Pradhan678438e2023-04-13 19:32:51 +00003550 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003551
3552 // Window should receive key down event.
3553 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3554
3555 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3556 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003557 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003558 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003559 AKEY_EVENT_FLAG_CANCELED);
3560}
3561
3562TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003563 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003564 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3565 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003566
Arthur Hung72d8dc32020-03-28 00:48:39 +00003567 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003568
Prabir Pradhan678438e2023-04-13 19:32:51 +00003569 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3570 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003571
3572 // Window should receive motion down event.
3573 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3574
3575 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3576 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003577 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003578 window->consumeMotionEvent(
3579 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003580}
3581
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003582TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3583 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3584 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3585 "Fake Window", ADISPLAY_ID_DEFAULT);
3586
3587 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3588
3589 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3590 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3591 .build());
3592
3593 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3594
3595 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3596 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3597 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3598
3599 // After the device has been reset, a new hovering stream can be sent to the window
3600 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3601 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3602 .build());
3603 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3604}
3605
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003606TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3607 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003608 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3609 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003610 window->setFocusable(true);
3611
3612 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3613 setFocusedWindow(window);
3614
3615 window->consumeFocusEvent(true);
3616
Prabir Pradhan678438e2023-04-13 19:32:51 +00003617 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003618 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3619 const nsecs_t injectTime = keyArgs.eventTime;
3620 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003621 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003622 // The dispatching time should be always greater than or equal to intercept key timeout.
3623 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3624 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3625 std::chrono::nanoseconds(interceptKeyTimeout).count());
3626}
3627
3628TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3629 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003630 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3631 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003632 window->setFocusable(true);
3633
3634 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3635 setFocusedWindow(window);
3636
3637 window->consumeFocusEvent(true);
3638
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003639 mFakePolicy->setInterceptKeyTimeout(150ms);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003640 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
3641 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003642
3643 // Window should receive key event immediately when same key up.
3644 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3645 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3646}
3647
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003648/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003649 * Two windows. First is a regular window. Second does not overlap with the first, and has
3650 * WATCH_OUTSIDE_TOUCH.
3651 * Both windows are owned by the same UID.
3652 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3653 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3654 */
3655TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3656 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3657 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3658 "First Window", ADISPLAY_ID_DEFAULT);
3659 window->setFrame(Rect{0, 0, 100, 100});
3660
3661 sp<FakeWindowHandle> outsideWindow =
3662 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3663 ADISPLAY_ID_DEFAULT);
3664 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3665 outsideWindow->setWatchOutsideTouch(true);
3666 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3667 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3668
3669 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003670 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3671 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3672 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003673 window->consumeMotionDown();
3674 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3675 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3676 outsideWindow->consumeMotionEvent(
3677 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3678}
3679
3680/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003681 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3682 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3683 * ACTION_OUTSIDE event is sent per gesture.
3684 */
3685TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3686 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3687 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003688 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3689 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003690 window->setWatchOutsideTouch(true);
3691 window->setFrame(Rect{0, 0, 100, 100});
3692 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003693 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3694 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003695 secondWindow->setFrame(Rect{100, 100, 200, 200});
3696 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003697 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3698 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003699 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3700 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3701
3702 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003703 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3704 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3705 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003706 window->assertNoEvents();
3707 secondWindow->assertNoEvents();
3708
3709 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3710 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003711 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3712 ADISPLAY_ID_DEFAULT,
3713 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003714 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3715 window->consumeMotionEvent(
3716 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003717 secondWindow->consumeMotionDown();
3718 thirdWindow->assertNoEvents();
3719
3720 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3721 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003722 mDispatcher->notifyMotion(
3723 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3724 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003725 window->assertNoEvents();
3726 secondWindow->consumeMotionMove();
3727 thirdWindow->consumeMotionDown();
3728}
3729
Prabir Pradhan814fe082022-07-22 20:22:18 +00003730TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003732 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3733 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003734 window->setFocusable(true);
3735
Patrick Williamsd828f302023-04-28 17:52:08 -05003736 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003737 setFocusedWindow(window);
3738
3739 window->consumeFocusEvent(true);
3740
Prabir Pradhan678438e2023-04-13 19:32:51 +00003741 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3742 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3743 mDispatcher->notifyKey(keyDown);
3744 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003745
3746 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3747 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3748
3749 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05003750 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003751
3752 window->consumeFocusEvent(false);
3753
Prabir Pradhan678438e2023-04-13 19:32:51 +00003754 mDispatcher->notifyKey(keyDown);
3755 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003756 window->assertNoEvents();
3757}
3758
Arthur Hung96483742022-11-15 03:30:48 +00003759TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3760 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3761 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3762 "Fake Window", ADISPLAY_ID_DEFAULT);
3763 // Ensure window is non-split and have some transform.
3764 window->setPreventSplitting(true);
3765 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05003766 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003767
3768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3769 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3770 {50, 50}))
3771 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3772 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3773
3774 const MotionEvent secondFingerDownEvent =
3775 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3776 .displayId(ADISPLAY_ID_DEFAULT)
3777 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003778 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3779 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003780 .build();
3781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3782 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3783 InputEventInjectionSync::WAIT_FOR_RESULT))
3784 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3785
3786 const MotionEvent* event = window->consumeMotion();
3787 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3788 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3789 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3790 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3791 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3792}
3793
Harry Cuttsb166c002023-05-09 13:06:05 +00003794TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
3795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3796 sp<FakeWindowHandle> window =
3797 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3798 window->setFrame(Rect(0, 0, 400, 400));
3799 sp<FakeWindowHandle> trustedOverlay =
3800 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
3801 ADISPLAY_ID_DEFAULT);
3802 trustedOverlay->setSpy(true);
3803 trustedOverlay->setTrustedOverlay(true);
3804
3805 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {trustedOverlay, window}}});
3806
3807 // Start a three-finger touchpad swipe
3808 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3809 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3810 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3811 .build());
3812 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3813 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3814 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3815 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3816 .build());
3817 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3818 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3819 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3820 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3821 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3822 .build());
3823
3824 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3825 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3826 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
3827
3828 // Move the swipe a bit
3829 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3830 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3831 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3832 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3833 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3834 .build());
3835
3836 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3837
3838 // End the swipe
3839 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3840 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3841 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3842 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3843 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3844 .build());
3845 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3846 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3847 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3848 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3849 .build());
3850 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3851 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3852 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3853 .build());
3854
3855 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
3856 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3857 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
3858
3859 window->assertNoEvents();
3860}
3861
3862TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
3863 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3864 sp<FakeWindowHandle> window =
3865 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3866 window->setFrame(Rect(0, 0, 400, 400));
3867 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3868
3869 // Start a three-finger touchpad swipe
3870 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3871 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3872 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3873 .build());
3874 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3875 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3876 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3877 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3878 .build());
3879 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3880 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3881 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3882 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3883 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3884 .build());
3885
3886 // Move the swipe a bit
3887 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3888 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3889 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3890 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3891 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3892 .build());
3893
3894 // End the swipe
3895 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3896 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3897 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3898 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3899 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3900 .build());
3901 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3902 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3903 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3904 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3905 .build());
3906 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3907 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3908 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3909 .build());
3910
3911 window->assertNoEvents();
3912}
3913
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003914/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003915 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
3916 * the first pointer.
3917 * Ensure that the second pointer is not sent to the window.
3918 *
3919 * The subsequent gesture should be correctly delivered to the window.
3920 */
3921TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
3922 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3923 sp<FakeWindowHandle> window =
3924 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3925 window->setFrame(Rect(0, 0, 400, 400));
3926 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3927
3928 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
3929 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3930 .downTime(baseTime + 10)
3931 .eventTime(baseTime + 10)
3932 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3933 .build());
3934
3935 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3936
3937 // We need a new window object for the same window, because dispatcher will store objects by
3938 // reference. That means that the testing code and the dispatcher will refer to the same shared
3939 // object. Calling window->setTransform here would affect dispatcher's comparison
3940 // of the old window to the new window, since both the old window and the new window would be
3941 // updated to the same value.
3942 sp<FakeWindowHandle> windowDup = window->duplicate();
3943
3944 // Change the transform so that the orientation is now different from original.
3945 windowDup->setWindowTransform(0, -1, 1, 0);
3946
3947 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDup}}});
3948
3949 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3950
3951 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3952 .downTime(baseTime + 10)
3953 .eventTime(baseTime + 30)
3954 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3955 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3956 .build());
3957
3958 // Finish the gesture and start a new one. Ensure the new gesture is sent to the window
3959 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
3960 .downTime(baseTime + 10)
3961 .eventTime(baseTime + 40)
3962 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3963 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3964 .build());
3965 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3966 .downTime(baseTime + 10)
3967 .eventTime(baseTime + 50)
3968 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3969 .build());
3970
3971 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3972 .downTime(baseTime + 60)
3973 .eventTime(baseTime + 60)
3974 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
3975 .build());
3976
3977 windowDup->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3978}
3979
3980/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003981 * Ensure the correct coordinate spaces are used by InputDispatcher.
3982 *
3983 * InputDispatcher works in the display space, so its coordinate system is relative to the display
3984 * panel. Windows get events in the window space, and get raw coordinates in the logical display
3985 * space.
3986 */
3987class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
3988public:
3989 void SetUp() override {
3990 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003991 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003992 }
3993
3994 void addDisplayInfo(int displayId, const ui::Transform& transform) {
3995 gui::DisplayInfo info;
3996 info.displayId = displayId;
3997 info.transform = transform;
3998 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05003999 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004000 }
4001
4002 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4003 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004004 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004005 }
4006
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004007 void removeAllWindowsAndDisplays() {
4008 mDisplayInfos.clear();
4009 mWindowInfos.clear();
4010 }
4011
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004012 // Set up a test scenario where the display has a scaled projection and there are two windows
4013 // on the display.
4014 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4015 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4016 // respectively.
4017 ui::Transform displayTransform;
4018 displayTransform.set(2, 0, 0, 4);
4019 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4020
4021 std::shared_ptr<FakeApplicationHandle> application =
4022 std::make_shared<FakeApplicationHandle>();
4023
4024 // Add two windows to the display. Their frames are represented in the display space.
4025 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004026 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4027 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004028 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4029 addWindow(firstWindow);
4030
4031 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004032 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4033 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004034 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4035 addWindow(secondWindow);
4036 return {std::move(firstWindow), std::move(secondWindow)};
4037 }
4038
4039private:
4040 std::vector<gui::DisplayInfo> mDisplayInfos;
4041 std::vector<gui::WindowInfo> mWindowInfos;
4042};
4043
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004044TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004045 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4046 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004047 // selected so that if the hit test was performed with the point and the bounds being in
4048 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004049 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4050 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4051 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004052
4053 firstWindow->consumeMotionDown();
4054 secondWindow->assertNoEvents();
4055}
4056
4057// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4058// the event should be treated as being in the logical display space.
4059TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4060 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4061 // Send down to the first window. The point is represented in the logical display space. The
4062 // point is selected so that if the hit test was done in logical display space, then it would
4063 // end up in the incorrect window.
4064 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4065 PointF{75 * 2, 55 * 4});
4066
4067 firstWindow->consumeMotionDown();
4068 secondWindow->assertNoEvents();
4069}
4070
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004071// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4072// event should be treated as being in the logical display space.
4073TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4074 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4075
4076 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4077 ui::Transform injectedEventTransform;
4078 injectedEventTransform.set(matrix);
4079 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4080 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4081
4082 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4083 .displayId(ADISPLAY_ID_DEFAULT)
4084 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004085 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004086 .x(untransformedPoint.x)
4087 .y(untransformedPoint.y))
4088 .build();
4089 event.transform(matrix);
4090
4091 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
4092 InputEventInjectionSync::WAIT_FOR_RESULT);
4093
4094 firstWindow->consumeMotionDown();
4095 secondWindow->assertNoEvents();
4096}
4097
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004098TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4099 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4100
4101 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004102 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4103 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4104 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004105
4106 firstWindow->assertNoEvents();
4107 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004108 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004109 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4110
4111 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4112 EXPECT_EQ(300, event->getRawX(0));
4113 EXPECT_EQ(880, event->getRawY(0));
4114
4115 // Ensure that the x and y values are in the window's coordinate space.
4116 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4117 // the logical display space. This will be the origin of the window space.
4118 EXPECT_EQ(100, event->getX(0));
4119 EXPECT_EQ(80, event->getY(0));
4120}
4121
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004122/** Ensure consistent behavior of InputDispatcher in all orientations. */
4123class InputDispatcherDisplayOrientationFixture
4124 : public InputDispatcherDisplayProjectionTest,
4125 public ::testing::WithParamInterface<ui::Rotation> {};
4126
4127// This test verifies the touchable region of a window for all rotations of the display by tapping
4128// in different locations on the display, specifically points close to the four corners of a
4129// window.
4130TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4131 constexpr static int32_t displayWidth = 400;
4132 constexpr static int32_t displayHeight = 800;
4133
4134 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4135
4136 const auto rotation = GetParam();
4137
4138 // Set up the display with the specified rotation.
4139 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4140 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4141 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4142 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4143 logicalDisplayWidth, logicalDisplayHeight);
4144 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4145
4146 // Create a window with its bounds determined in the logical display.
4147 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4148 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4149 sp<FakeWindowHandle> window =
4150 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4151 window->setFrame(frameInDisplay, displayTransform);
4152 addWindow(window);
4153
4154 // The following points in logical display space should be inside the window.
4155 static const std::array<vec2, 4> insidePoints{
4156 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4157 for (const auto pointInsideWindow : insidePoints) {
4158 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4159 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004160 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4161 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4162 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004163 window->consumeMotionDown();
4164
Prabir Pradhan678438e2023-04-13 19:32:51 +00004165 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4166 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4167 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004168 window->consumeMotionUp();
4169 }
4170
4171 // The following points in logical display space should be outside the window.
4172 static const std::array<vec2, 5> outsidePoints{
4173 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4174 for (const auto pointOutsideWindow : outsidePoints) {
4175 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4176 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004177 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4178 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4179 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004180
Prabir Pradhan678438e2023-04-13 19:32:51 +00004181 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4182 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4183 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004184 }
4185 window->assertNoEvents();
4186}
4187
4188// Run the precision tests for all rotations.
4189INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4190 InputDispatcherDisplayOrientationFixture,
4191 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4192 ui::ROTATION_270),
4193 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4194 return ftl::enum_string(testParamInfo.param);
4195 });
4196
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004197using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4198 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004199
4200class TransferTouchFixture : public InputDispatcherTest,
4201 public ::testing::WithParamInterface<TransferFunction> {};
4202
4203TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004204 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004205
4206 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004207 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004208 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4209 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004210 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004211 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004212 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4213 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004214 sp<FakeWindowHandle> wallpaper =
4215 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4216 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004217 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004218 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004219
4220 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004221 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4222 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004223
Svet Ganov5d3bc372020-01-26 23:11:07 -08004224 // Only the first window should get the down event
4225 firstWindow->consumeMotionDown();
4226 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004227 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004228
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004229 // Transfer touch to the second window
4230 TransferFunction f = GetParam();
4231 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4232 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004233 // The first window gets cancel and the second gets down
4234 firstWindow->consumeMotionCancel();
4235 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004236 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004237
4238 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004239 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4240 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004241 // The first window gets no events and the second gets up
4242 firstWindow->assertNoEvents();
4243 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004244 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004245}
4246
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004247/**
4248 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4249 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4250 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4251 * natural to the user.
4252 * In this test, we are sending a pointer to both spy window and first window. We then try to
4253 * transfer touch to the second window. The dispatcher should identify the first window as the
4254 * one that should lose the gesture, and therefore the action should be to move the gesture from
4255 * the first window to the second.
4256 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4257 * the other API, as well.
4258 */
4259TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4260 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4261
4262 // Create a couple of windows + a spy window
4263 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004264 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004265 spyWindow->setTrustedOverlay(true);
4266 spyWindow->setSpy(true);
4267 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004268 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004269 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004270 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004271
4272 // Add the windows to the dispatcher
4273 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4274
4275 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004276 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4277 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004278 // Only the first window and spy should get the down event
4279 spyWindow->consumeMotionDown();
4280 firstWindow->consumeMotionDown();
4281
4282 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4283 // if f === 'transferTouch'.
4284 TransferFunction f = GetParam();
4285 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4286 ASSERT_TRUE(success);
4287 // The first window gets cancel and the second gets down
4288 firstWindow->consumeMotionCancel();
4289 secondWindow->consumeMotionDown();
4290
4291 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004292 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4293 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004294 // The first window gets no events and the second+spy get up
4295 firstWindow->assertNoEvents();
4296 spyWindow->consumeMotionUp();
4297 secondWindow->consumeMotionUp();
4298}
4299
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004300TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004301 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004302
4303 PointF touchPoint = {10, 10};
4304
4305 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004306 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004307 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4308 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004309 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004310 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004311 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4312 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004313 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004314
4315 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004316 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004317
4318 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004319 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4320 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4321 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004322 // Only the first window should get the down event
4323 firstWindow->consumeMotionDown();
4324 secondWindow->assertNoEvents();
4325
4326 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004327 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4328 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004329 // Only the first window should get the pointer down event
4330 firstWindow->consumeMotionPointerDown(1);
4331 secondWindow->assertNoEvents();
4332
4333 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004334 TransferFunction f = GetParam();
4335 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4336 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004337 // The first window gets cancel and the second gets down and pointer down
4338 firstWindow->consumeMotionCancel();
4339 secondWindow->consumeMotionDown();
4340 secondWindow->consumeMotionPointerDown(1);
4341
4342 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004343 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4344 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004345 // The first window gets nothing and the second gets pointer up
4346 firstWindow->assertNoEvents();
4347 secondWindow->consumeMotionPointerUp(1);
4348
4349 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004350 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4351 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004352 // The first window gets nothing and the second gets up
4353 firstWindow->assertNoEvents();
4354 secondWindow->consumeMotionUp();
4355}
4356
Arthur Hungc539dbb2022-12-08 07:45:36 +00004357TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4359
4360 // Create a couple of windows
4361 sp<FakeWindowHandle> firstWindow =
4362 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4363 ADISPLAY_ID_DEFAULT);
4364 firstWindow->setDupTouchToWallpaper(true);
4365 sp<FakeWindowHandle> secondWindow =
4366 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4367 ADISPLAY_ID_DEFAULT);
4368 secondWindow->setDupTouchToWallpaper(true);
4369
4370 sp<FakeWindowHandle> wallpaper1 =
4371 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4372 wallpaper1->setIsWallpaper(true);
4373
4374 sp<FakeWindowHandle> wallpaper2 =
4375 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4376 wallpaper2->setIsWallpaper(true);
4377 // Add the windows to the dispatcher
4378 mDispatcher->setInputWindows(
4379 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4380
4381 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004382 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4383 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004384
4385 // Only the first window should get the down event
4386 firstWindow->consumeMotionDown();
4387 secondWindow->assertNoEvents();
4388 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4389 wallpaper2->assertNoEvents();
4390
4391 // Transfer touch focus to the second window
4392 TransferFunction f = GetParam();
4393 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4394 ASSERT_TRUE(success);
4395
4396 // The first window gets cancel and the second gets down
4397 firstWindow->consumeMotionCancel();
4398 secondWindow->consumeMotionDown();
4399 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4400 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4401
4402 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004403 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4404 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004405 // The first window gets no events and the second gets up
4406 firstWindow->assertNoEvents();
4407 secondWindow->consumeMotionUp();
4408 wallpaper1->assertNoEvents();
4409 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4410}
4411
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004412// For the cases of single pointer touch and two pointers non-split touch, the api's
4413// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4414// for the case where there are multiple pointers split across several windows.
4415INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4416 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004417 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4418 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004419 return dispatcher->transferTouch(destChannelToken,
4420 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004421 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004422 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4423 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004424 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004425 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004426 }));
4427
Svet Ganov5d3bc372020-01-26 23:11:07 -08004428TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004429 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004430
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004431 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004432 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4433 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004434 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004435
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004436 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004437 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4438 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004439 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004440
4441 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004442 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004443
4444 PointF pointInFirst = {300, 200};
4445 PointF pointInSecond = {300, 600};
4446
4447 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004448 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4449 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4450 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004451 // Only the first window should get the down event
4452 firstWindow->consumeMotionDown();
4453 secondWindow->assertNoEvents();
4454
4455 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004456 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4457 ADISPLAY_ID_DEFAULT,
4458 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004459 // The first window gets a move and the second a down
4460 firstWindow->consumeMotionMove();
4461 secondWindow->consumeMotionDown();
4462
4463 // Transfer touch focus to the second window
4464 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4465 // The first window gets cancel and the new gets pointer down (it already saw down)
4466 firstWindow->consumeMotionCancel();
4467 secondWindow->consumeMotionPointerDown(1);
4468
4469 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004470 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4471 ADISPLAY_ID_DEFAULT,
4472 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004473 // The first window gets nothing and the second gets pointer up
4474 firstWindow->assertNoEvents();
4475 secondWindow->consumeMotionPointerUp(1);
4476
4477 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004478 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4479 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004480 // The first window gets nothing and the second gets up
4481 firstWindow->assertNoEvents();
4482 secondWindow->consumeMotionUp();
4483}
4484
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004485// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4486// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4487// touch is not supported, so the touch should continue on those windows and the transferred-to
4488// window should get nothing.
4489TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4490 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4491
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004492 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004493 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4494 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004495 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004496
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004497 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004498 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4499 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004500 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004501
4502 // Add the windows to the dispatcher
4503 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4504
4505 PointF pointInFirst = {300, 200};
4506 PointF pointInSecond = {300, 600};
4507
4508 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004509 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4510 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4511 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004512 // Only the first window should get the down event
4513 firstWindow->consumeMotionDown();
4514 secondWindow->assertNoEvents();
4515
4516 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004517 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4518 ADISPLAY_ID_DEFAULT,
4519 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004520 // The first window gets a move and the second a down
4521 firstWindow->consumeMotionMove();
4522 secondWindow->consumeMotionDown();
4523
4524 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004525 const bool transferred =
4526 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004527 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4528 ASSERT_FALSE(transferred);
4529 firstWindow->assertNoEvents();
4530 secondWindow->assertNoEvents();
4531
4532 // The rest of the dispatch should proceed as normal
4533 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004534 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4535 ADISPLAY_ID_DEFAULT,
4536 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004537 // The first window gets MOVE and the second gets pointer up
4538 firstWindow->consumeMotionMove();
4539 secondWindow->consumeMotionUp();
4540
4541 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004542 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4543 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004544 // The first window gets nothing and the second gets up
4545 firstWindow->consumeMotionUp();
4546 secondWindow->assertNoEvents();
4547}
4548
Arthur Hungabbb9d82021-09-01 14:52:30 +00004549// This case will create two windows and one mirrored window on the default display and mirror
4550// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4551// the windows info of second display before default display.
4552TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4553 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4554 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004555 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004556 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004557 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004558 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004559 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004560
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004561 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004562 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004563
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004564 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004565 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004566
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004567 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004568 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004569
4570 // Update window info, let it find window handle of second display first.
4571 mDispatcher->setInputWindows(
4572 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4573 {ADISPLAY_ID_DEFAULT,
4574 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4575
4576 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4577 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4578 {50, 50}))
4579 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4580
4581 // Window should receive motion event.
4582 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4583
4584 // Transfer touch focus
4585 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4586 secondWindowInPrimary->getToken()));
4587 // The first window gets cancel.
4588 firstWindowInPrimary->consumeMotionCancel();
4589 secondWindowInPrimary->consumeMotionDown();
4590
4591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4592 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4593 ADISPLAY_ID_DEFAULT, {150, 50}))
4594 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4595 firstWindowInPrimary->assertNoEvents();
4596 secondWindowInPrimary->consumeMotionMove();
4597
4598 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4599 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4600 {150, 50}))
4601 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4602 firstWindowInPrimary->assertNoEvents();
4603 secondWindowInPrimary->consumeMotionUp();
4604}
4605
4606// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4607// 'transferTouch' api.
4608TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4609 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4610 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004611 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004612 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004613 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004614 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004615 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004616
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004617 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004618 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004619
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004620 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004621 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004622
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004623 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004624 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004625
4626 // Update window info, let it find window handle of second display first.
4627 mDispatcher->setInputWindows(
4628 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4629 {ADISPLAY_ID_DEFAULT,
4630 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4631
4632 // Touch on second display.
4633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4634 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4635 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4636
4637 // Window should receive motion event.
4638 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4639
4640 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004641 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004642
4643 // The first window gets cancel.
4644 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4645 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4646
4647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4648 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4649 SECOND_DISPLAY_ID, {150, 50}))
4650 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4651 firstWindowInPrimary->assertNoEvents();
4652 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4653
4654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4655 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4656 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4657 firstWindowInPrimary->assertNoEvents();
4658 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4659}
4660
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004661TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004662 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004663 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4664 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004665
Vishnu Nair47074b82020-08-14 11:54:47 -07004666 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004667 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004668 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004669
4670 window->consumeFocusEvent(true);
4671
Prabir Pradhan678438e2023-04-13 19:32:51 +00004672 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004673
4674 // Window should receive key down event.
4675 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004676
4677 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004678 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004679 mFakePolicy->assertUserActivityPoked();
4680}
4681
4682TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4683 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4684 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4685 "Fake Window", ADISPLAY_ID_DEFAULT);
4686
4687 window->setDisableUserActivity(true);
4688 window->setFocusable(true);
4689 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4690 setFocusedWindow(window);
4691
4692 window->consumeFocusEvent(true);
4693
4694 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4695
4696 // Window should receive key down event.
4697 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4698
4699 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004700 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004701 mFakePolicy->assertUserActivityNotPoked();
4702}
4703
4704TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4705 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4706 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4707 "Fake Window", ADISPLAY_ID_DEFAULT);
4708
4709 window->setFocusable(true);
4710 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4711 setFocusedWindow(window);
4712
4713 window->consumeFocusEvent(true);
4714
4715 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4716 mDispatcher->waitForIdle();
4717
4718 // System key is not passed down
4719 window->assertNoEvents();
4720
4721 // Should have poked user activity
4722 mFakePolicy->assertUserActivityPoked();
4723}
4724
4725TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4726 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4727 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4728 "Fake Window", ADISPLAY_ID_DEFAULT);
4729
4730 window->setFocusable(true);
4731 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4732 setFocusedWindow(window);
4733
4734 window->consumeFocusEvent(true);
4735
4736 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4737 mDispatcher->waitForIdle();
4738
4739 // System key is not passed down
4740 window->assertNoEvents();
4741
4742 // Should have poked user activity
4743 mFakePolicy->assertUserActivityPoked();
4744}
4745
4746TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4747 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4748 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4749 "Fake Window", ADISPLAY_ID_DEFAULT);
4750
4751 window->setDisableUserActivity(true);
4752 window->setFocusable(true);
4753 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4754 setFocusedWindow(window);
4755
4756 window->consumeFocusEvent(true);
4757
4758 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4759 mDispatcher->waitForIdle();
4760
4761 // System key is not passed down
4762 window->assertNoEvents();
4763
4764 // Should have poked user activity
4765 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004766}
4767
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004768TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
4769 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4770 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4771 "Fake Window", ADISPLAY_ID_DEFAULT);
4772
4773 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4774
4775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4776 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4777 ADISPLAY_ID_DEFAULT, {100, 100}))
4778 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4779
4780 window->consumeMotionEvent(
4781 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
4782
4783 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004784 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004785 mFakePolicy->assertUserActivityPoked();
4786}
4787
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004788TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004789 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004790 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4791 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004792
Arthur Hung72d8dc32020-03-28 00:48:39 +00004793 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004794
Prabir Pradhan678438e2023-04-13 19:32:51 +00004795 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004796 mDispatcher->waitForIdle();
4797
4798 window->assertNoEvents();
4799}
4800
4801// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4802TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004803 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004804 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4805 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004806
Arthur Hung72d8dc32020-03-28 00:48:39 +00004807 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004808
4809 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004810 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004811 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004812 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4813 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004814
4815 // Window should receive only the motion event
4816 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4817 window->assertNoEvents(); // Key event or focus event will not be received
4818}
4819
arthurhungea3f4fc2020-12-21 23:18:53 +08004820TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4821 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4822
arthurhungea3f4fc2020-12-21 23:18:53 +08004823 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004824 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4825 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004826 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004827
arthurhungea3f4fc2020-12-21 23:18:53 +08004828 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004829 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4830 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004831 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004832
4833 // Add the windows to the dispatcher
4834 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4835
4836 PointF pointInFirst = {300, 200};
4837 PointF pointInSecond = {300, 600};
4838
4839 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004840 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4841 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4842 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004843 // Only the first window should get the down event
4844 firstWindow->consumeMotionDown();
4845 secondWindow->assertNoEvents();
4846
4847 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004848 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4849 ADISPLAY_ID_DEFAULT,
4850 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004851 // The first window gets a move and the second a down
4852 firstWindow->consumeMotionMove();
4853 secondWindow->consumeMotionDown();
4854
4855 // Send pointer cancel to the second window
4856 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004857 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004858 {pointInFirst, pointInSecond});
4859 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004860 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004861 // The first window gets move and the second gets cancel.
4862 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4863 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4864
4865 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004866 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4867 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004868 // The first window gets up and the second gets nothing.
4869 firstWindow->consumeMotionUp();
4870 secondWindow->assertNoEvents();
4871}
4872
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004873TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4874 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4875
4876 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004877 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004878 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4879 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4880 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4881 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4882
Harry Cutts33476232023-01-30 19:57:29 +00004883 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004884 window->assertNoEvents();
4885 mDispatcher->waitForIdle();
4886}
4887
chaviwd1c23182019-12-20 18:44:56 -08004888class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004889public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004890 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004891 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004892 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004893 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004894 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004895 }
4896
chaviwd1c23182019-12-20 18:44:56 -08004897 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4898
4899 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004900 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4901 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004902 }
4903
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004904 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4905
4906 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4907
chaviwd1c23182019-12-20 18:44:56 -08004908 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004909 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004910 expectedDisplayId, expectedFlags);
4911 }
4912
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004913 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004914 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004915 expectedDisplayId, expectedFlags);
4916 }
4917
chaviwd1c23182019-12-20 18:44:56 -08004918 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004919 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004920 expectedDisplayId, expectedFlags);
4921 }
4922
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004923 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004924 mInputReceiver->consumeMotionEvent(
4925 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4926 WithDisplayId(expectedDisplayId),
4927 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004928 }
4929
Arthur Hungfbfa5722021-11-16 02:45:54 +00004930 void consumeMotionPointerDown(int32_t pointerIdx) {
4931 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4932 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004933 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004934 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004935 }
4936
Evan Rosky84f07f02021-04-16 10:42:42 -07004937 MotionEvent* consumeMotion() {
4938 InputEvent* event = mInputReceiver->consume();
4939 if (!event) {
4940 ADD_FAILURE() << "No event was produced";
4941 return nullptr;
4942 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004943 if (event->getType() != InputEventType::MOTION) {
4944 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07004945 return nullptr;
4946 }
4947 return static_cast<MotionEvent*>(event);
4948 }
4949
chaviwd1c23182019-12-20 18:44:56 -08004950 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4951
4952private:
4953 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004954};
4955
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004956using InputDispatcherMonitorTest = InputDispatcherTest;
4957
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004958/**
4959 * Two entities that receive touch: A window, and a global monitor.
4960 * The touch goes to the window, and then the window disappears.
4961 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4962 * for the monitor, as well.
4963 * 1. foregroundWindow
4964 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4965 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004966TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004967 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4968 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004969 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004970
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004971 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004972
4973 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4975 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4976 {100, 200}))
4977 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4978
4979 // Both the foreground window and the global monitor should receive the touch down
4980 window->consumeMotionDown();
4981 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4982
4983 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4984 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4985 ADISPLAY_ID_DEFAULT, {110, 200}))
4986 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4987
4988 window->consumeMotionMove();
4989 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
4990
4991 // Now the foreground window goes away
4992 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
4993 window->consumeMotionCancel();
4994 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
4995
4996 // If more events come in, there will be no more foreground window to send them to. This will
4997 // cause a cancel for the monitor, as well.
4998 ASSERT_EQ(InputEventInjectionResult::FAILED,
4999 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5000 ADISPLAY_ID_DEFAULT, {120, 200}))
5001 << "Injection should fail because the window was removed";
5002 window->assertNoEvents();
5003 // Global monitor now gets the cancel
5004 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5005}
5006
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005007TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005008 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005009 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5010 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005011 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005012
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005013 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005014
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005016 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005017 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005018 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005019 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005020}
5021
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005022TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5023 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005024
Chris Yea209fde2020-07-22 13:54:51 -07005025 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005026 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5027 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005028 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005029
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005031 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005032 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005033 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005034 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005035
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005036 // Pilfer pointers from the monitor.
5037 // This should not do anything and the window should continue to receive events.
5038 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005039
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005040 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005041 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5042 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005043 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005044
5045 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5046 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005047}
5048
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005049TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005050 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005051 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5052 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005053 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5054 window->setWindowOffset(20, 40);
5055 window->setWindowTransform(0, 1, -1, 0);
5056
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005057 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005058
5059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5060 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5061 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5062 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5063 MotionEvent* event = monitor.consumeMotion();
5064 // Even though window has transform, gesture monitor must not.
5065 ASSERT_EQ(ui::Transform(), event->getTransform());
5066}
5067
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005068TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005069 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005070 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005071
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005072 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00005073 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005074 << "Injection should fail if there is a monitor, but no touchable window";
5075 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005076}
5077
chaviw81e2bb92019-12-18 15:03:51 -08005078TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005079 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005080 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5081 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005082
Arthur Hung72d8dc32020-03-28 00:48:39 +00005083 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08005084
5085 NotifyMotionArgs motionArgs =
5086 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5087 ADISPLAY_ID_DEFAULT);
5088
Prabir Pradhan678438e2023-04-13 19:32:51 +00005089 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005090 // Window should receive motion down event.
5091 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5092
5093 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005094 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005095 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5096 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5097 motionArgs.pointerCoords[0].getX() - 10);
5098
Prabir Pradhan678438e2023-04-13 19:32:51 +00005099 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005100 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005101 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005102}
5103
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005104/**
5105 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5106 * the device default right away. In the test scenario, we check both the default value,
5107 * and the action of enabling / disabling.
5108 */
5109TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005110 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005111 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5112 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005113 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005114
5115 // Set focused application.
5116 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005117 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005118
5119 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00005120 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005121 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005122 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005123
5124 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005125 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005126 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005127 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005128
5129 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005130 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005131 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005132 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005133 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005134 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005135 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005136 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005137
5138 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005139 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005140 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005141 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005142
5143 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005144 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005145 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005146 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005147 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005148 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005149 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005150 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005151
5152 window->assertNoEvents();
5153}
5154
Gang Wange9087892020-01-07 12:17:14 -05005155TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005156 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005157 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5158 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005159
5160 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005161 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005162
Arthur Hung72d8dc32020-03-28 00:48:39 +00005163 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005164 setFocusedWindow(window);
5165
Harry Cutts33476232023-01-30 19:57:29 +00005166 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005167
Prabir Pradhan678438e2023-04-13 19:32:51 +00005168 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5169 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005170
5171 InputEvent* event = window->consume();
5172 ASSERT_NE(event, nullptr);
5173
5174 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5175 ASSERT_NE(verified, nullptr);
5176 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5177
5178 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5179 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5180 ASSERT_EQ(keyArgs.source, verified->source);
5181 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5182
5183 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5184
5185 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005186 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005187 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005188 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5189 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5190 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5191 ASSERT_EQ(0, verifiedKey.repeatCount);
5192}
5193
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005194TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005195 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005196 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5197 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005198
5199 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5200
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005201 ui::Transform transform;
5202 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5203
5204 gui::DisplayInfo displayInfo;
5205 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5206 displayInfo.transform = transform;
5207
Patrick Williamsd828f302023-04-28 17:52:08 -05005208 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005209
Prabir Pradhan678438e2023-04-13 19:32:51 +00005210 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005211 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5212 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005213 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005214
5215 InputEvent* event = window->consume();
5216 ASSERT_NE(event, nullptr);
5217
5218 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5219 ASSERT_NE(verified, nullptr);
5220 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5221
5222 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5223 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5224 EXPECT_EQ(motionArgs.source, verified->source);
5225 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5226
5227 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5228
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005229 const vec2 rawXY =
5230 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5231 motionArgs.pointerCoords[0].getXYValue());
5232 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5233 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005234 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005235 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005236 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005237 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5238 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5239}
5240
chaviw09c8d2d2020-08-24 15:48:26 -07005241/**
5242 * Ensure that separate calls to sign the same data are generating the same key.
5243 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5244 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5245 * tests.
5246 */
5247TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5248 KeyEvent event = getTestKeyEvent();
5249 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5250
5251 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5252 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5253 ASSERT_EQ(hmac1, hmac2);
5254}
5255
5256/**
5257 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5258 */
5259TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5260 KeyEvent event = getTestKeyEvent();
5261 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5262 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5263
5264 verifiedEvent.deviceId += 1;
5265 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5266
5267 verifiedEvent.source += 1;
5268 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5269
5270 verifiedEvent.eventTimeNanos += 1;
5271 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5272
5273 verifiedEvent.displayId += 1;
5274 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5275
5276 verifiedEvent.action += 1;
5277 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5278
5279 verifiedEvent.downTimeNanos += 1;
5280 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5281
5282 verifiedEvent.flags += 1;
5283 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5284
5285 verifiedEvent.keyCode += 1;
5286 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5287
5288 verifiedEvent.scanCode += 1;
5289 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5290
5291 verifiedEvent.metaState += 1;
5292 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5293
5294 verifiedEvent.repeatCount += 1;
5295 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5296}
5297
Vishnu Nair958da932020-08-21 17:12:37 -07005298TEST_F(InputDispatcherTest, SetFocusedWindow) {
5299 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5300 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005301 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005302 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005303 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005304 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5305
5306 // Top window is also focusable but is not granted focus.
5307 windowTop->setFocusable(true);
5308 windowSecond->setFocusable(true);
5309 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5310 setFocusedWindow(windowSecond);
5311
5312 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5314 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005315
5316 // Focused window should receive event.
5317 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5318 windowTop->assertNoEvents();
5319}
5320
5321TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5322 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5323 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005324 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005325 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5326
5327 window->setFocusable(true);
5328 // Release channel for window is no longer valid.
5329 window->releaseChannel();
5330 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5331 setFocusedWindow(window);
5332
5333 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005334 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5335 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005336
5337 // window channel is invalid, so it should not receive any input event.
5338 window->assertNoEvents();
5339}
5340
5341TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5342 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5343 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005344 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005345 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005346 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5347
Vishnu Nair958da932020-08-21 17:12:37 -07005348 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5349 setFocusedWindow(window);
5350
5351 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005352 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5353 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005354
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005355 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005356 window->assertNoEvents();
5357}
5358
5359TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5360 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5361 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005362 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005363 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005364 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005365 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5366
5367 windowTop->setFocusable(true);
5368 windowSecond->setFocusable(true);
5369 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5370 setFocusedWindow(windowTop);
5371 windowTop->consumeFocusEvent(true);
5372
Chavi Weingarten847e8512023-03-29 00:26:09 +00005373 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5374 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005375 windowSecond->consumeFocusEvent(true);
5376 windowTop->consumeFocusEvent(false);
5377
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005378 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5379 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005380
5381 // Focused window should receive event.
5382 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5383}
5384
Chavi Weingarten847e8512023-03-29 00:26:09 +00005385TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005386 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5387 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005388 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005389 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005390 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005391 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5392
5393 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005394 windowSecond->setFocusable(false);
5395 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005396 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005397 setFocusedWindow(windowTop);
5398 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005399
Chavi Weingarten847e8512023-03-29 00:26:09 +00005400 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5401 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005402
5403 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005404 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005405 windowSecond->assertNoEvents();
5406}
5407
5408TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5409 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5410 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005411 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005412 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005413 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5414 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005415 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5416
5417 window->setFocusable(true);
5418 previousFocusedWindow->setFocusable(true);
5419 window->setVisible(false);
5420 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5421 setFocusedWindow(previousFocusedWindow);
5422 previousFocusedWindow->consumeFocusEvent(true);
5423
5424 // Requesting focus on invisible window takes focus from currently focused window.
5425 setFocusedWindow(window);
5426 previousFocusedWindow->consumeFocusEvent(false);
5427
5428 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005430 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5431 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005432
5433 // Window does not get focus event or key down.
5434 window->assertNoEvents();
5435
5436 // Window becomes visible.
5437 window->setVisible(true);
5438 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5439
5440 // Window receives focus event.
5441 window->consumeFocusEvent(true);
5442 // Focused window receives key down.
5443 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5444}
5445
Vishnu Nair599f1412021-06-21 10:39:58 -07005446TEST_F(InputDispatcherTest, DisplayRemoved) {
5447 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5448 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005449 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005450 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5451
5452 // window is granted focus.
5453 window->setFocusable(true);
5454 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5455 setFocusedWindow(window);
5456 window->consumeFocusEvent(true);
5457
5458 // When a display is removed window loses focus.
5459 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5460 window->consumeFocusEvent(false);
5461}
5462
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005463/**
5464 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5465 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5466 * of the 'slipperyEnterWindow'.
5467 *
5468 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5469 * a way so that the touched location is no longer covered by the top window.
5470 *
5471 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5472 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5473 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5474 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5475 * with ACTION_DOWN).
5476 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5477 * window moved itself away from the touched location and had Flag::SLIPPERY.
5478 *
5479 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5480 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5481 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5482 *
5483 * In this test, we ensure that the event received by the bottom window has
5484 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5485 */
5486TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00005487 constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
5488 constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005489
5490 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5491 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5492
5493 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005494 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005495 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005496 // Make sure this one overlaps the bottom window
5497 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5498 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5499 // one. Windows with the same owner are not considered to be occluding each other.
5500 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5501
5502 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005503 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005504 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5505
5506 mDispatcher->setInputWindows(
5507 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5508
5509 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005510 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5511 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5512 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005513 slipperyExitWindow->consumeMotionDown();
5514 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5515 mDispatcher->setInputWindows(
5516 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5517
Prabir Pradhan678438e2023-04-13 19:32:51 +00005518 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5519 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5520 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005521
5522 slipperyExitWindow->consumeMotionCancel();
5523
5524 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5525 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5526}
5527
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005528/**
5529 * Two windows, one on the left and another on the right. The left window is slippery. The right
5530 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5531 * touch moves from the left window into the right window, the gesture should continue to go to the
5532 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5533 * reproduces a crash.
5534 */
5535TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5536 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5537
5538 sp<FakeWindowHandle> leftSlipperyWindow =
5539 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5540 leftSlipperyWindow->setSlippery(true);
5541 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5542
5543 sp<FakeWindowHandle> rightDropTouchesWindow =
5544 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5545 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5546 rightDropTouchesWindow->setDropInput(true);
5547
5548 mDispatcher->setInputWindows(
5549 {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}});
5550
5551 // Start touch in the left window
5552 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5553 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5554 .build());
5555 leftSlipperyWindow->consumeMotionDown();
5556
5557 // And move it into the right window
5558 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5559 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5560 .build());
5561
5562 // Since the right window isn't eligible to receive input, touch does not slip.
5563 // The left window continues to receive the gesture.
5564 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5565 rightDropTouchesWindow->assertNoEvents();
5566}
5567
Garfield Tan1c7bc862020-01-28 13:24:04 -08005568class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5569protected:
5570 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5571 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5572
Chris Yea209fde2020-07-22 13:54:51 -07005573 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005574 sp<FakeWindowHandle> mWindow;
5575
5576 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005577 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005578 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Prabir Pradhana41d2442023-04-20 21:30:40 +00005579 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Prabir Pradhan87112a72023-04-20 19:13:39 +00005580 mDispatcher->requestRefreshConfiguration();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005581 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
5582 ASSERT_EQ(OK, mDispatcher->start());
5583
5584 setUpWindow();
5585 }
5586
5587 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005588 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005589 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005590
Vishnu Nair47074b82020-08-14 11:54:47 -07005591 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005592 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005593 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005594 mWindow->consumeFocusEvent(true);
5595 }
5596
Chris Ye2ad95392020-09-01 13:44:44 -07005597 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005598 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005599 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005600 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005601 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005602
5603 // Window should receive key down event.
5604 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5605 }
5606
5607 void expectKeyRepeatOnce(int32_t repeatCount) {
5608 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5609 InputEvent* repeatEvent = mWindow->consume();
5610 ASSERT_NE(nullptr, repeatEvent);
5611
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005612 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005613
5614 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5615 uint32_t eventAction = repeatKeyEvent->getAction();
5616 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5617 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5618 }
5619
Chris Ye2ad95392020-09-01 13:44:44 -07005620 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005621 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005622 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005623 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005624 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005625
5626 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005627 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005628 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005629 }
5630};
5631
5632TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005633 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005634 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5635 expectKeyRepeatOnce(repeatCount);
5636 }
5637}
5638
5639TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005640 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005641 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5642 expectKeyRepeatOnce(repeatCount);
5643 }
Harry Cutts33476232023-01-30 19:57:29 +00005644 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005645 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005646 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5647 expectKeyRepeatOnce(repeatCount);
5648 }
5649}
5650
5651TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005652 sendAndConsumeKeyDown(/*deviceId=*/1);
5653 expectKeyRepeatOnce(/*repeatCount=*/1);
5654 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005655 mWindow->assertNoEvents();
5656}
5657
5658TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005659 sendAndConsumeKeyDown(/*deviceId=*/1);
5660 expectKeyRepeatOnce(/*repeatCount=*/1);
5661 sendAndConsumeKeyDown(/*deviceId=*/2);
5662 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005663 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005664 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005665 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005666 expectKeyRepeatOnce(/*repeatCount=*/2);
5667 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005668 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005669 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005670 mWindow->assertNoEvents();
5671}
5672
5673TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005674 sendAndConsumeKeyDown(/*deviceId=*/1);
5675 expectKeyRepeatOnce(/*repeatCount=*/1);
5676 sendAndConsumeKeyDown(/*deviceId=*/2);
5677 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005678 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005679 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005680 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005681 mWindow->assertNoEvents();
5682}
5683
liushenxiang42232912021-05-21 20:24:09 +08005684TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5685 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005686 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005687 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005688 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5689 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5690 mWindow->assertNoEvents();
5691}
5692
Garfield Tan1c7bc862020-01-28 13:24:04 -08005693TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005694 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005695 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005696 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5697 InputEvent* repeatEvent = mWindow->consume();
5698 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5699 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5700 IdGenerator::getSource(repeatEvent->getId()));
5701 }
5702}
5703
5704TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005705 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005706 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005707
5708 std::unordered_set<int32_t> idSet;
5709 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5710 InputEvent* repeatEvent = mWindow->consume();
5711 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5712 int32_t id = repeatEvent->getId();
5713 EXPECT_EQ(idSet.end(), idSet.find(id));
5714 idSet.insert(id);
5715 }
5716}
5717
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005718/* Test InputDispatcher for MultiDisplay */
5719class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5720public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005721 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005722 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005723
Chris Yea209fde2020-07-22 13:54:51 -07005724 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005725 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005726 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005727
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005728 // Set focus window for primary display, but focused display would be second one.
5729 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005730 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005731 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005732 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005733 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005734
Chris Yea209fde2020-07-22 13:54:51 -07005735 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005736 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005737 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005738 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005739 // Set focus display to second one.
5740 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5741 // Set focus window for second display.
5742 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005743 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005744 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005745 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005746 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005747 }
5748
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005749 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005750 InputDispatcherTest::TearDown();
5751
Chris Yea209fde2020-07-22 13:54:51 -07005752 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005753 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005754 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005755 windowInSecondary.clear();
5756 }
5757
5758protected:
Chris Yea209fde2020-07-22 13:54:51 -07005759 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005760 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005761 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005762 sp<FakeWindowHandle> windowInSecondary;
5763};
5764
5765TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5766 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5768 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5769 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005770 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005771 windowInSecondary->assertNoEvents();
5772
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005773 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5775 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5776 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005777 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005778 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005779}
5780
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005781TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005782 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005783 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5784 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005785 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005786 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005787 windowInSecondary->assertNoEvents();
5788
5789 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005790 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005791 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005792 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005793 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005794
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005795 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005796 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005797
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005798 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005799 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005800 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005801
5802 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005803 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005804 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005805 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005806 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005807 windowInSecondary->assertNoEvents();
5808}
5809
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005810// Test per-display input monitors for motion event.
5811TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005812 FakeMonitorReceiver monitorInPrimary =
5813 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5814 FakeMonitorReceiver monitorInSecondary =
5815 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005816
5817 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005818 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5819 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5820 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005821 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005822 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005823 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005824 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005825
5826 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5828 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5829 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005830 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005831 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005832 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005833 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005834
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005835 // Lift up the touch from the second display
5836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5837 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5838 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5839 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5840 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5841
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005842 // Test inject a non-pointer motion event.
5843 // If specific a display, it will dispatch to the focused window of particular display,
5844 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5846 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5847 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005848 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005849 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005850 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005851 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005852}
5853
5854// Test per-display input monitors for key event.
5855TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005856 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005857 FakeMonitorReceiver monitorInPrimary =
5858 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5859 FakeMonitorReceiver monitorInSecondary =
5860 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005861
5862 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5864 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005865 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005866 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005867 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005868 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005869}
5870
Vishnu Nair958da932020-08-21 17:12:37 -07005871TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
5872 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005873 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005874 secondWindowInPrimary->setFocusable(true);
5875 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
5876 setFocusedWindow(secondWindowInPrimary);
5877 windowInPrimary->consumeFocusEvent(false);
5878 secondWindowInPrimary->consumeFocusEvent(true);
5879
5880 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005881 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
5882 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005883 windowInPrimary->assertNoEvents();
5884 windowInSecondary->assertNoEvents();
5885 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5886}
5887
Arthur Hungdfd528e2021-12-08 13:23:04 +00005888TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
5889 FakeMonitorReceiver monitorInPrimary =
5890 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5891 FakeMonitorReceiver monitorInSecondary =
5892 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
5893
5894 // Test touch down on primary display.
5895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5896 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5897 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5898 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5899 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5900
5901 // Test touch down on second display.
5902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5903 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5904 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5905 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
5906 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
5907
5908 // Trigger cancel touch.
5909 mDispatcher->cancelCurrentTouch();
5910 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5911 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5912 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
5913 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
5914
5915 // Test inject a move motion event, no window/monitor should receive the event.
5916 ASSERT_EQ(InputEventInjectionResult::FAILED,
5917 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5918 ADISPLAY_ID_DEFAULT, {110, 200}))
5919 << "Inject motion event should return InputEventInjectionResult::FAILED";
5920 windowInPrimary->assertNoEvents();
5921 monitorInPrimary.assertNoEvents();
5922
5923 ASSERT_EQ(InputEventInjectionResult::FAILED,
5924 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5925 SECOND_DISPLAY_ID, {110, 200}))
5926 << "Inject motion event should return InputEventInjectionResult::FAILED";
5927 windowInSecondary->assertNoEvents();
5928 monitorInSecondary.assertNoEvents();
5929}
5930
Jackal Guof9696682018-10-05 12:23:23 +08005931class InputFilterTest : public InputDispatcherTest {
5932protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005933 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
5934 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08005935 NotifyMotionArgs motionArgs;
5936
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005937 motionArgs =
5938 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005939 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005940 motionArgs =
5941 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005942 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005943 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005944 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005945 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
5946 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08005947 } else {
5948 mFakePolicy->assertFilterInputEventWasNotCalled();
5949 }
5950 }
5951
5952 void testNotifyKey(bool expectToBeFiltered) {
5953 NotifyKeyArgs keyArgs;
5954
5955 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005956 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08005957 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005958 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005959 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005960
5961 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08005962 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08005963 } else {
5964 mFakePolicy->assertFilterInputEventWasNotCalled();
5965 }
5966 }
5967};
5968
5969// Test InputFilter for MotionEvent
5970TEST_F(InputFilterTest, MotionEvent_InputFilter) {
5971 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
5972 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5973 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5974
5975 // Enable InputFilter
5976 mDispatcher->setInputFilterEnabled(true);
5977 // Test touch on both primary and second display, and check if both events are filtered.
5978 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
5979 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
5980
5981 // Disable InputFilter
5982 mDispatcher->setInputFilterEnabled(false);
5983 // Test touch on both primary and second display, and check if both events aren't filtered.
5984 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5985 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5986}
5987
5988// Test InputFilter for KeyEvent
5989TEST_F(InputFilterTest, KeyEvent_InputFilter) {
5990 // Since the InputFilter is disabled by default, check if key event aren't filtered.
5991 testNotifyKey(/*expectToBeFiltered*/ false);
5992
5993 // Enable InputFilter
5994 mDispatcher->setInputFilterEnabled(true);
5995 // Send a key event, and check if it is filtered.
5996 testNotifyKey(/*expectToBeFiltered*/ true);
5997
5998 // Disable InputFilter
5999 mDispatcher->setInputFilterEnabled(false);
6000 // Send a key event, and check if it isn't filtered.
6001 testNotifyKey(/*expectToBeFiltered*/ false);
6002}
6003
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006004// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6005// logical display coordinate space.
6006TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6007 ui::Transform firstDisplayTransform;
6008 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6009 ui::Transform secondDisplayTransform;
6010 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6011
6012 std::vector<gui::DisplayInfo> displayInfos(2);
6013 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6014 displayInfos[0].transform = firstDisplayTransform;
6015 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6016 displayInfos[1].transform = secondDisplayTransform;
6017
Patrick Williamsd828f302023-04-28 17:52:08 -05006018 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006019
6020 // Enable InputFilter
6021 mDispatcher->setInputFilterEnabled(true);
6022
6023 // Ensure the correct transforms are used for the displays.
6024 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
6025 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
6026}
6027
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006028class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6029protected:
6030 virtual void SetUp() override {
6031 InputDispatcherTest::SetUp();
6032
6033 /**
6034 * We don't need to enable input filter to test the injected event policy, but we enabled it
6035 * here to make the tests more realistic, since this policy only matters when inputfilter is
6036 * on.
6037 */
6038 mDispatcher->setInputFilterEnabled(true);
6039
6040 std::shared_ptr<InputApplicationHandle> application =
6041 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006042 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6043 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006044
6045 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6046 mWindow->setFocusable(true);
6047 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6048 setFocusedWindow(mWindow);
6049 mWindow->consumeFocusEvent(true);
6050 }
6051
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006052 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6053 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006054 KeyEvent event;
6055
6056 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6057 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6058 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006059 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006060 const int32_t additionalPolicyFlags =
6061 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006063 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006064 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6065 policyFlags | additionalPolicyFlags));
6066
6067 InputEvent* received = mWindow->consume();
6068 ASSERT_NE(nullptr, received);
6069 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006070 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006071 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
6072 ASSERT_EQ(flags, keyEvent.getFlags());
6073 }
6074
6075 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6076 int32_t flags) {
6077 MotionEvent event;
6078 PointerProperties pointerProperties[1];
6079 PointerCoords pointerCoords[1];
6080 pointerProperties[0].clear();
6081 pointerProperties[0].id = 0;
6082 pointerCoords[0].clear();
6083 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6084 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6085
6086 ui::Transform identityTransform;
6087 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6088 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6089 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6090 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6091 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006092 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006093 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006094 /*pointerCount*/ 1, pointerProperties, pointerCoords);
6095
6096 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006098 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006099 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6100 policyFlags | additionalPolicyFlags));
6101
6102 InputEvent* received = mWindow->consume();
6103 ASSERT_NE(nullptr, received);
6104 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006105 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006106 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
6107 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006108 }
6109
6110private:
6111 sp<FakeWindowHandle> mWindow;
6112};
6113
6114TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006115 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6116 // filter. Without it, the event will no different from a regularly injected event, and the
6117 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006118 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6119 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006120}
6121
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006122TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006123 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006124 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006125 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6126}
6127
6128TEST_F(InputFilterInjectionPolicyTest,
6129 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6130 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006131 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006132 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006133}
6134
6135TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006136 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6137 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006138}
6139
chaviwfd6d3512019-03-25 13:23:49 -07006140class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006141 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006142 InputDispatcherTest::SetUp();
6143
Chris Yea209fde2020-07-22 13:54:51 -07006144 std::shared_ptr<FakeApplicationHandle> application =
6145 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006146 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006147 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006148 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006149
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006150 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006151 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006152 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006153
6154 // Set focused application.
6155 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006156 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006157
6158 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00006159 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006160 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006161 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006162 }
6163
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006164 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006165 InputDispatcherTest::TearDown();
6166
6167 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006168 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006169 }
6170
6171protected:
6172 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006173 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006174 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006175};
6176
6177// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6178// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6179// the onPointerDownOutsideFocus callback.
6180TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006181 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006182 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6183 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006184 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006185 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006186
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006187 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006188 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6189}
6190
6191// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6192// DOWN on the window that doesn't have focus. Ensure no window received the
6193// onPointerDownOutsideFocus callback.
6194TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006196 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006197 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006198 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006199
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006200 ASSERT_TRUE(mDispatcher->waitForIdle());
6201 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006202}
6203
6204// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6205// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6206TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006207 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6208 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006209 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006210 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006211
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006212 ASSERT_TRUE(mDispatcher->waitForIdle());
6213 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006214}
6215
6216// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6217// DOWN on the window that already has focus. Ensure no window received the
6218// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006219TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006220 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006221 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006222 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006223 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006224 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006225
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006226 ASSERT_TRUE(mDispatcher->waitForIdle());
6227 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006228}
6229
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006230// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6231// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6232TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6233 const MotionEvent event =
6234 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6235 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006236 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006237 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6238 .build();
6239 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6240 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6241 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6242
6243 ASSERT_TRUE(mDispatcher->waitForIdle());
6244 mFakePolicy->assertOnPointerDownWasNotCalled();
6245 // Ensure that the unfocused window did not receive any FOCUS events.
6246 mUnfocusedWindow->assertNoEvents();
6247}
6248
chaviwaf87b3e2019-10-01 16:59:28 -07006249// These tests ensures we can send touch events to a single client when there are multiple input
6250// windows that point to the same client token.
6251class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6252 virtual void SetUp() override {
6253 InputDispatcherTest::SetUp();
6254
Chris Yea209fde2020-07-22 13:54:51 -07006255 std::shared_ptr<FakeApplicationHandle> application =
6256 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006257 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6258 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006259 mWindow1->setFrame(Rect(0, 0, 100, 100));
6260
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006261 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6262 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006263 mWindow2->setFrame(Rect(100, 100, 200, 200));
6264
Arthur Hung72d8dc32020-03-28 00:48:39 +00006265 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006266 }
6267
6268protected:
6269 sp<FakeWindowHandle> mWindow1;
6270 sp<FakeWindowHandle> mWindow2;
6271
6272 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006273 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006274 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6275 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006276 }
6277
6278 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6279 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006280 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006281 InputEvent* event = window->consume();
6282
6283 ASSERT_NE(nullptr, event) << name.c_str()
6284 << ": consumer should have returned non-NULL event.";
6285
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006286 ASSERT_EQ(InputEventType::MOTION, event->getType())
6287 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006288
6289 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006290 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006291 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006292
6293 for (size_t i = 0; i < points.size(); i++) {
6294 float expectedX = points[i].x;
6295 float expectedY = points[i].y;
6296
6297 EXPECT_EQ(expectedX, motionEvent.getX(i))
6298 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6299 << ", got " << motionEvent.getX(i);
6300 EXPECT_EQ(expectedY, motionEvent.getY(i))
6301 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6302 << ", got " << motionEvent.getY(i);
6303 }
6304 }
chaviw9eaa22c2020-07-01 16:21:27 -07006305
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006306 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006307 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006308 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6309 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006310
6311 // Always consume from window1 since it's the window that has the InputReceiver
6312 consumeMotionEvent(mWindow1, action, expectedPoints);
6313 }
chaviwaf87b3e2019-10-01 16:59:28 -07006314};
6315
6316TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6317 // Touch Window 1
6318 PointF touchedPoint = {10, 10};
6319 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006320 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006321
6322 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006323 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006324
6325 // Touch Window 2
6326 touchedPoint = {150, 150};
6327 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006328 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006329}
6330
chaviw9eaa22c2020-07-01 16:21:27 -07006331TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6332 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006333 mWindow2->setWindowScale(0.5f, 0.5f);
6334
6335 // Touch Window 1
6336 PointF touchedPoint = {10, 10};
6337 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006338 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006339 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006340 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006341
6342 // Touch Window 2
6343 touchedPoint = {150, 150};
6344 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006345 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6346 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006347
chaviw9eaa22c2020-07-01 16:21:27 -07006348 // Update the transform so rotation is set
6349 mWindow2->setWindowTransform(0, -1, 1, 0);
6350 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6351 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006352}
6353
chaviw9eaa22c2020-07-01 16:21:27 -07006354TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006355 mWindow2->setWindowScale(0.5f, 0.5f);
6356
6357 // Touch Window 1
6358 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6359 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006360 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006361
6362 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006363 touchedPoints.push_back(PointF{150, 150});
6364 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006365 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006366
chaviw9eaa22c2020-07-01 16:21:27 -07006367 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006368 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006369 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006370
chaviw9eaa22c2020-07-01 16:21:27 -07006371 // Update the transform so rotation is set for Window 2
6372 mWindow2->setWindowTransform(0, -1, 1, 0);
6373 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006374 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006375}
6376
chaviw9eaa22c2020-07-01 16:21:27 -07006377TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006378 mWindow2->setWindowScale(0.5f, 0.5f);
6379
6380 // Touch Window 1
6381 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6382 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006383 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006384
6385 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006386 touchedPoints.push_back(PointF{150, 150});
6387 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006388
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006389 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006390
6391 // Move both windows
6392 touchedPoints = {{20, 20}, {175, 175}};
6393 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6394 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6395
chaviw9eaa22c2020-07-01 16:21:27 -07006396 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006397
chaviw9eaa22c2020-07-01 16:21:27 -07006398 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006399 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006400 expectedPoints.pop_back();
6401
6402 // Touch Window 2
6403 mWindow2->setWindowTransform(0, -1, 1, 0);
6404 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006405 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006406
6407 // Move both windows
6408 touchedPoints = {{20, 20}, {175, 175}};
6409 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6410 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6411
6412 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006413}
6414
6415TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6416 mWindow1->setWindowScale(0.5f, 0.5f);
6417
6418 // Touch Window 1
6419 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6420 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006421 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006422
6423 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006424 touchedPoints.push_back(PointF{150, 150});
6425 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006426
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006427 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006428
6429 // Move both windows
6430 touchedPoints = {{20, 20}, {175, 175}};
6431 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6432 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6433
chaviw9eaa22c2020-07-01 16:21:27 -07006434 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006435}
6436
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006437/**
6438 * When one of the windows is slippery, the touch should not slip into the other window with the
6439 * same input channel.
6440 */
6441TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6442 mWindow1->setSlippery(true);
6443 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6444
6445 // Touch down in window 1
6446 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6447 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6448 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6449
6450 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6451 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6452 // getting generated.
6453 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6454 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6455
6456 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6457}
6458
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006459/**
6460 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
6461 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
6462 * that the pointer is hovering over may have a different transform.
6463 */
6464TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
6465 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6466
6467 // Start hover in window 1
6468 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
6469 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6470 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6471 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
6472
6473 // Move hover to window 2.
6474 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6475 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6476
6477 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
6478 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6479 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
6480}
6481
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006482class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6483 virtual void SetUp() override {
6484 InputDispatcherTest::SetUp();
6485
Chris Yea209fde2020-07-22 13:54:51 -07006486 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006487 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006488 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6489 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006490 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006491 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006492 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006493
6494 // Set focused application.
6495 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6496
6497 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006498 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006499 mWindow->consumeFocusEvent(true);
6500 }
6501
6502 virtual void TearDown() override {
6503 InputDispatcherTest::TearDown();
6504 mWindow.clear();
6505 }
6506
6507protected:
Chris Yea209fde2020-07-22 13:54:51 -07006508 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006509 sp<FakeWindowHandle> mWindow;
6510 static constexpr PointF WINDOW_LOCATION = {20, 20};
6511
6512 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006514 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6515 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006516 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006517 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6518 WINDOW_LOCATION));
6519 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006520
6521 sp<FakeWindowHandle> addSpyWindow() {
6522 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006523 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006524 spy->setTrustedOverlay(true);
6525 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006526 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006527 spy->setDispatchingTimeout(30ms);
6528 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6529 return spy;
6530 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006531};
6532
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006533// Send a tap and respond, which should not cause an ANR.
6534TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6535 tapOnWindow();
6536 mWindow->consumeMotionDown();
6537 mWindow->consumeMotionUp();
6538 ASSERT_TRUE(mDispatcher->waitForIdle());
6539 mFakePolicy->assertNotifyAnrWasNotCalled();
6540}
6541
6542// Send a regular key and respond, which should not cause an ANR.
6543TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006544 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006545 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6546 ASSERT_TRUE(mDispatcher->waitForIdle());
6547 mFakePolicy->assertNotifyAnrWasNotCalled();
6548}
6549
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006550TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6551 mWindow->setFocusable(false);
6552 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6553 mWindow->consumeFocusEvent(false);
6554
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006555 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006556 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6557 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6558 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006560 // Key will not go to window because we have no focused window.
6561 // The 'no focused window' ANR timer should start instead.
6562
6563 // Now, the focused application goes away.
6564 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6565 // The key should get dropped and there should be no ANR.
6566
6567 ASSERT_TRUE(mDispatcher->waitForIdle());
6568 mFakePolicy->assertNotifyAnrWasNotCalled();
6569}
6570
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006571// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006572// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6573// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006574TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006575 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006576 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6577 WINDOW_LOCATION));
6578
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006579 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6580 ASSERT_TRUE(sequenceNum);
6581 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006582 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006583
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006584 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006585 mWindow->consumeMotionEvent(
6586 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006587 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006588 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006589}
6590
6591// Send a key to the app and have the app not respond right away.
6592TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6593 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006594 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006595 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6596 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006597 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006598 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006599 ASSERT_TRUE(mDispatcher->waitForIdle());
6600}
6601
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006602// We have a focused application, but no focused window
6603TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006604 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006605 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6606 mWindow->consumeFocusEvent(false);
6607
6608 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006610 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6611 WINDOW_LOCATION));
6612 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6613 mDispatcher->waitForIdle();
6614 mFakePolicy->assertNotifyAnrWasNotCalled();
6615
6616 // Once a focused event arrives, we get an ANR for this application
6617 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6618 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006619 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006620 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6621 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006622 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006623 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006624 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006625 ASSERT_TRUE(mDispatcher->waitForIdle());
6626}
6627
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006628/**
6629 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6630 * there will not be an ANR.
6631 */
6632TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6633 mWindow->setFocusable(false);
6634 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6635 mWindow->consumeFocusEvent(false);
6636
6637 KeyEvent event;
6638 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6639 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6640
6641 // Define a valid key down event that is stale (too old).
6642 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6643 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006644 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006645
6646 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6647
6648 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006649 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006650 InputEventInjectionSync::WAIT_FOR_RESULT,
6651 INJECT_EVENT_TIMEOUT, policyFlags);
6652 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6653 << "Injection should fail because the event is stale";
6654
6655 ASSERT_TRUE(mDispatcher->waitForIdle());
6656 mFakePolicy->assertNotifyAnrWasNotCalled();
6657 mWindow->assertNoEvents();
6658}
6659
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006660// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006661// Make sure that we don't notify policy twice about the same ANR.
6662TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006663 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006664 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6665 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006666
6667 // Once a focused event arrives, we get an ANR for this application
6668 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6669 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006670 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006671 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6672 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006673 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006674 const std::chrono::duration appTimeout =
6675 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6676 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006677
Vishnu Naire4df8752022-09-08 09:17:55 -07006678 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006679 // ANR should not be raised again. It is up to policy to do that if it desires.
6680 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006681
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006682 // If we now get a focused window, the ANR should stop, but the policy handles that via
6683 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006684 ASSERT_TRUE(mDispatcher->waitForIdle());
6685}
6686
6687// We have a focused application, but no focused window
6688TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006689 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006690 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6691 mWindow->consumeFocusEvent(false);
6692
6693 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006694 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006695 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006696 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6697 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006698
Vishnu Naire4df8752022-09-08 09:17:55 -07006699 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6700 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006701
6702 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006703 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006704 ASSERT_TRUE(mDispatcher->waitForIdle());
6705 mWindow->assertNoEvents();
6706}
6707
6708/**
6709 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6710 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6711 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6712 * the ANR mechanism should still work.
6713 *
6714 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6715 * DOWN event, while not responding on the second one.
6716 */
6717TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6718 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6719 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6720 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6721 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6722 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006723 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006724
6725 // Now send ACTION_UP, with identical timestamp
6726 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6727 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6728 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6729 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006730 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006731
6732 // We have now sent down and up. Let's consume first event and then ANR on the second.
6733 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6734 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006735 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006736}
6737
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006738// A spy window can receive an ANR
6739TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6740 sp<FakeWindowHandle> spy = addSpyWindow();
6741
6742 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6743 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6744 WINDOW_LOCATION));
6745 mWindow->consumeMotionDown();
6746
6747 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6748 ASSERT_TRUE(sequenceNum);
6749 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006750 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006751
6752 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006753 spy->consumeMotionEvent(
6754 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006755 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006756 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006757}
6758
6759// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006760// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006761TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6762 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006763
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006764 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6765 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006766 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006768
6769 // Stuck on the ACTION_UP
6770 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006771 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006772
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006773 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006774 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006775 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6776 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006777
6778 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6779 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006780 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006781 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006782 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006783}
6784
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006785// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006786// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006787TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6788 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006789
6790 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006791 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6792 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006793
6794 mWindow->consumeMotionDown();
6795 // Stuck on the ACTION_UP
6796 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006797 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006798
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006799 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006800 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006801 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6802 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006803
6804 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6805 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006806 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006807 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006808 spy->assertNoEvents();
6809}
6810
6811TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6812 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6813
6814 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6815
6816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6817 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6818 WINDOW_LOCATION));
6819
6820 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6821 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6822 ASSERT_TRUE(consumeSeq);
6823
Prabir Pradhanedd96402022-02-15 01:46:16 -08006824 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006825
6826 monitor.finishEvent(*consumeSeq);
6827 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6828
6829 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006830 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006831}
6832
6833// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6834// process events, you don't get an anr. When the window later becomes unresponsive again, you
6835// get an ANR again.
6836// 1. tap -> block on ACTION_UP -> receive ANR
6837// 2. consume all pending events (= queue becomes healthy again)
6838// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6839TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6840 tapOnWindow();
6841
6842 mWindow->consumeMotionDown();
6843 // Block on ACTION_UP
6844 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006845 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006846 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6847 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006848 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006849 mWindow->assertNoEvents();
6850
6851 tapOnWindow();
6852 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006853 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006854 mWindow->consumeMotionUp();
6855
6856 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006857 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006858 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006859 mWindow->assertNoEvents();
6860}
6861
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006862// If a connection remains unresponsive for a while, make sure policy is only notified once about
6863// it.
6864TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006866 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6867 WINDOW_LOCATION));
6868
6869 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006870 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006871 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006872 // 'notifyConnectionUnresponsive' should only be called once per connection
6873 mFakePolicy->assertNotifyAnrWasNotCalled();
6874 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006875 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006876 mWindow->consumeMotionEvent(
6877 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006878 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006879 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006880 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006881 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006882}
6883
6884/**
6885 * If a window is processing a motion event, and then a key event comes in, the key event should
6886 * not to to the focused window until the motion is processed.
6887 *
6888 * Warning!!!
6889 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
6890 * and the injection timeout that we specify when injecting the key.
6891 * We must have the injection timeout (10ms) be smaller than
6892 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
6893 *
6894 * If that value changes, this test should also change.
6895 */
6896TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
6897 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6898 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6899
6900 tapOnWindow();
6901 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6902 ASSERT_TRUE(downSequenceNum);
6903 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6904 ASSERT_TRUE(upSequenceNum);
6905 // Don't finish the events yet, and send a key
6906 // Injection will "succeed" because we will eventually give up and send the key to the focused
6907 // window even if motions are still being processed. But because the injection timeout is short,
6908 // we will receive INJECTION_TIMED_OUT as the result.
6909
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006910 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006911 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006912 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6913 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006914 // Key will not be sent to the window, yet, because the window is still processing events
6915 // and the key remains pending, waiting for the touch events to be processed
6916 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6917 ASSERT_FALSE(keySequenceNum);
6918
6919 std::this_thread::sleep_for(500ms);
6920 // if we wait long enough though, dispatcher will give up, and still send the key
6921 // to the focused window, even though we have not yet finished the motion event
6922 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6923 mWindow->finishEvent(*downSequenceNum);
6924 mWindow->finishEvent(*upSequenceNum);
6925}
6926
6927/**
6928 * If a window is processing a motion event, and then a key event comes in, the key event should
6929 * not go to the focused window until the motion is processed.
6930 * If then a new motion comes in, then the pending key event should be going to the currently
6931 * focused window right away.
6932 */
6933TEST_F(InputDispatcherSingleWindowAnr,
6934 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
6935 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6936 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6937
6938 tapOnWindow();
6939 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6940 ASSERT_TRUE(downSequenceNum);
6941 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6942 ASSERT_TRUE(upSequenceNum);
6943 // Don't finish the events yet, and send a key
6944 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006946 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6947 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006948 // At this point, key is still pending, and should not be sent to the application yet.
6949 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6950 ASSERT_FALSE(keySequenceNum);
6951
6952 // Now tap down again. It should cause the pending key to go to the focused window right away.
6953 tapOnWindow();
6954 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
6955 // the other events yet. We can finish events in any order.
6956 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
6957 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
6958 mWindow->consumeMotionDown();
6959 mWindow->consumeMotionUp();
6960 mWindow->assertNoEvents();
6961}
6962
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006963/**
6964 * Send an event to the app and have the app not respond right away.
6965 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6966 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
6967 * At some point, the window becomes responsive again.
6968 * Ensure that subsequent events get dropped, and the next gesture is delivered.
6969 */
6970TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
6971 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6972 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
6973 .build());
6974
6975 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6976 ASSERT_TRUE(sequenceNum);
6977 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6978 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
6979
6980 mWindow->finishEvent(*sequenceNum);
6981 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6982 ASSERT_TRUE(mDispatcher->waitForIdle());
6983 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
6984
6985 // Now that the window is responsive, let's continue the gesture.
6986 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6987 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
6988 .build());
6989
6990 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6991 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
6992 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
6993 .build());
6994
6995 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
6996 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
6997 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
6998 .build());
6999 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7000 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7001 .build());
7002 // We already canceled this pointer, so the window shouldn't get any new events.
7003 mWindow->assertNoEvents();
7004
7005 // Start another one.
7006 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7007 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7008 .build());
7009 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7010}
7011
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007012class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7013 virtual void SetUp() override {
7014 InputDispatcherTest::SetUp();
7015
Chris Yea209fde2020-07-22 13:54:51 -07007016 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007017 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007018 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7019 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007020 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007021 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007022 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007023
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007024 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7025 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05007026 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007027 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007028
7029 // Set focused application.
7030 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007031 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007032
7033 // Expect one focus window exist in display.
7034 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007035 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007036 mFocusedWindow->consumeFocusEvent(true);
7037 }
7038
7039 virtual void TearDown() override {
7040 InputDispatcherTest::TearDown();
7041
7042 mUnfocusedWindow.clear();
7043 mFocusedWindow.clear();
7044 }
7045
7046protected:
Chris Yea209fde2020-07-22 13:54:51 -07007047 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007048 sp<FakeWindowHandle> mUnfocusedWindow;
7049 sp<FakeWindowHandle> mFocusedWindow;
7050 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7051 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7052 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7053
7054 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7055
7056 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7057
7058private:
7059 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007061 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7062 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007063 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007064 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7065 location));
7066 }
7067};
7068
7069// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7070// should be ANR'd first.
7071TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007072 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007073 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7074 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007075 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007076 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007077 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007078 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007079 // We consumed all events, so no ANR
7080 ASSERT_TRUE(mDispatcher->waitForIdle());
7081 mFakePolicy->assertNotifyAnrWasNotCalled();
7082
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007083 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007084 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7085 FOCUSED_WINDOW_LOCATION));
7086 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7087 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007088
7089 const std::chrono::duration timeout =
7090 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007091 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007092 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7093 // sequence to make it consistent
7094 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007095 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007096 mFocusedWindow->consumeMotionDown();
7097 // This cancel is generated because the connection was unresponsive
7098 mFocusedWindow->consumeMotionCancel();
7099 mFocusedWindow->assertNoEvents();
7100 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007101 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007102 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7103 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007104 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007105}
7106
7107// If we have 2 windows with identical timeouts that are both unresponsive,
7108// it doesn't matter which order they should have ANR.
7109// But we should receive ANR for both.
7110TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7111 // Set the timeout for unfocused window to match the focused window
7112 mUnfocusedWindow->setDispatchingTimeout(10ms);
7113 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7114
7115 tapOnFocusedWindow();
7116 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08007117 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
7118 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
7119 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007120
7121 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007122 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
7123 mFocusedWindow->getToken() == anrConnectionToken2);
7124 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
7125 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007126
7127 ASSERT_TRUE(mDispatcher->waitForIdle());
7128 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007129
7130 mFocusedWindow->consumeMotionDown();
7131 mFocusedWindow->consumeMotionUp();
7132 mUnfocusedWindow->consumeMotionOutside();
7133
Prabir Pradhanedd96402022-02-15 01:46:16 -08007134 sp<IBinder> responsiveToken1, responsiveToken2;
7135 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
7136 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007137
7138 // Both applications should be marked as responsive, in any order
7139 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
7140 mFocusedWindow->getToken() == responsiveToken2);
7141 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
7142 mUnfocusedWindow->getToken() == responsiveToken2);
7143 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007144}
7145
7146// If a window is already not responding, the second tap on the same window should be ignored.
7147// We should also log an error to account for the dropped event (not tested here).
7148// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7149TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7150 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007151 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007152 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007153 // Receive the events, but don't respond
7154 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7155 ASSERT_TRUE(downEventSequenceNum);
7156 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7157 ASSERT_TRUE(upEventSequenceNum);
7158 const std::chrono::duration timeout =
7159 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007160 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007161
7162 // Tap once again
7163 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007164 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007165 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7166 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007167 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007168 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7169 FOCUSED_WINDOW_LOCATION));
7170 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7171 // valid touch target
7172 mUnfocusedWindow->assertNoEvents();
7173
7174 // Consume the first tap
7175 mFocusedWindow->finishEvent(*downEventSequenceNum);
7176 mFocusedWindow->finishEvent(*upEventSequenceNum);
7177 ASSERT_TRUE(mDispatcher->waitForIdle());
7178 // The second tap did not go to the focused window
7179 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007180 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007181 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7182 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007183 mFakePolicy->assertNotifyAnrWasNotCalled();
7184}
7185
7186// If you tap outside of all windows, there will not be ANR
7187TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007188 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007189 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7190 LOCATION_OUTSIDE_ALL_WINDOWS));
7191 ASSERT_TRUE(mDispatcher->waitForIdle());
7192 mFakePolicy->assertNotifyAnrWasNotCalled();
7193}
7194
7195// Since the focused window is paused, tapping on it should not produce any events
7196TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7197 mFocusedWindow->setPaused(true);
7198 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7199
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007200 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007201 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7202 FOCUSED_WINDOW_LOCATION));
7203
7204 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7205 ASSERT_TRUE(mDispatcher->waitForIdle());
7206 // Should not ANR because the window is paused, and touches shouldn't go to it
7207 mFakePolicy->assertNotifyAnrWasNotCalled();
7208
7209 mFocusedWindow->assertNoEvents();
7210 mUnfocusedWindow->assertNoEvents();
7211}
7212
7213/**
7214 * If a window is processing a motion event, and then a key event comes in, the key event should
7215 * not to to the focused window until the motion is processed.
7216 * If a different window becomes focused at this time, the key should go to that window instead.
7217 *
7218 * Warning!!!
7219 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7220 * and the injection timeout that we specify when injecting the key.
7221 * We must have the injection timeout (10ms) be smaller than
7222 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7223 *
7224 * If that value changes, this test should also change.
7225 */
7226TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7227 // Set a long ANR timeout to prevent it from triggering
7228 mFocusedWindow->setDispatchingTimeout(2s);
7229 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7230
7231 tapOnUnfocusedWindow();
7232 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7233 ASSERT_TRUE(downSequenceNum);
7234 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7235 ASSERT_TRUE(upSequenceNum);
7236 // Don't finish the events yet, and send a key
7237 // Injection will succeed because we will eventually give up and send the key to the focused
7238 // window even if motions are still being processed.
7239
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007240 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007241 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7242 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007243 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007244 // Key will not be sent to the window, yet, because the window is still processing events
7245 // and the key remains pending, waiting for the touch events to be processed
7246 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7247 ASSERT_FALSE(keySequenceNum);
7248
7249 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007250 mFocusedWindow->setFocusable(false);
7251 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007252 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007253 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007254
7255 // Focus events should precede the key events
7256 mUnfocusedWindow->consumeFocusEvent(true);
7257 mFocusedWindow->consumeFocusEvent(false);
7258
7259 // Finish the tap events, which should unblock dispatcher
7260 mUnfocusedWindow->finishEvent(*downSequenceNum);
7261 mUnfocusedWindow->finishEvent(*upSequenceNum);
7262
7263 // Now that all queues are cleared and no backlog in the connections, the key event
7264 // can finally go to the newly focused "mUnfocusedWindow".
7265 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7266 mFocusedWindow->assertNoEvents();
7267 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007268 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007269}
7270
7271// When the touch stream is split across 2 windows, and one of them does not respond,
7272// then ANR should be raised and the touch should be canceled for the unresponsive window.
7273// The other window should not be affected by that.
7274TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7275 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007276 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7277 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7278 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007279 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007280 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007281
7282 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007283 mDispatcher->notifyMotion(
7284 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7285 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007286
7287 const std::chrono::duration timeout =
7288 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007289 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007290
7291 mUnfocusedWindow->consumeMotionDown();
7292 mFocusedWindow->consumeMotionDown();
7293 // Focused window may or may not receive ACTION_MOVE
7294 // But it should definitely receive ACTION_CANCEL due to the ANR
7295 InputEvent* event;
7296 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7297 ASSERT_TRUE(moveOrCancelSequenceNum);
7298 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7299 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007300 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007301 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7302 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7303 mFocusedWindow->consumeMotionCancel();
7304 } else {
7305 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7306 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007307 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007308 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7309 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007310
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007311 mUnfocusedWindow->assertNoEvents();
7312 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007313 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007314}
7315
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007316/**
7317 * If we have no focused window, and a key comes in, we start the ANR timer.
7318 * The focused application should add a focused window before the timer runs out to prevent ANR.
7319 *
7320 * If the user touches another application during this time, the key should be dropped.
7321 * Next, if a new focused window comes in, without toggling the focused application,
7322 * then no ANR should occur.
7323 *
7324 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7325 * but in some cases the policy may not update the focused application.
7326 */
7327TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7328 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7329 std::make_shared<FakeApplicationHandle>();
7330 focusedApplication->setDispatchingTimeout(60ms);
7331 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7332 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7333 mFocusedWindow->setFocusable(false);
7334
7335 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7336 mFocusedWindow->consumeFocusEvent(false);
7337
7338 // Send a key. The ANR timer should start because there is no focused window.
7339 // 'focusedApplication' will get blamed if this timer completes.
7340 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007341 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007342 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7343 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
7344 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007346
7347 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7348 // then the injected touches won't cause the focused event to get dropped.
7349 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7350 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7351 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7352 // For this test, it means that the key would get delivered to the window once it becomes
7353 // focused.
7354 std::this_thread::sleep_for(10ms);
7355
7356 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007357 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7358 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7359 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007360
7361 // We do not consume the motion right away, because that would require dispatcher to first
7362 // process (== drop) the key event, and by that time, ANR will be raised.
7363 // Set the focused window first.
7364 mFocusedWindow->setFocusable(true);
7365 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7366 setFocusedWindow(mFocusedWindow);
7367 mFocusedWindow->consumeFocusEvent(true);
7368 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7369 // to another application. This could be a bug / behaviour in the policy.
7370
7371 mUnfocusedWindow->consumeMotionDown();
7372
7373 ASSERT_TRUE(mDispatcher->waitForIdle());
7374 // Should not ANR because we actually have a focused window. It was just added too slowly.
7375 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7376}
7377
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007378// These tests ensure we cannot send touch events to a window that's positioned behind a window
7379// that has feature NO_INPUT_CHANNEL.
7380// Layout:
7381// Top (closest to user)
7382// mNoInputWindow (above all windows)
7383// mBottomWindow
7384// Bottom (furthest from user)
7385class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7386 virtual void SetUp() override {
7387 InputDispatcherTest::SetUp();
7388
7389 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007390 mNoInputWindow =
7391 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7392 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007393 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007394 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007395 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7396 // It's perfectly valid for this window to not have an associated input channel
7397
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007398 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7399 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007400 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7401
7402 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7403 }
7404
7405protected:
7406 std::shared_ptr<FakeApplicationHandle> mApplication;
7407 sp<FakeWindowHandle> mNoInputWindow;
7408 sp<FakeWindowHandle> mBottomWindow;
7409};
7410
7411TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7412 PointF touchedPoint = {10, 10};
7413
Prabir Pradhan678438e2023-04-13 19:32:51 +00007414 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7415 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7416 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007417
7418 mNoInputWindow->assertNoEvents();
7419 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7420 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7421 // and therefore should prevent mBottomWindow from receiving touches
7422 mBottomWindow->assertNoEvents();
7423}
7424
7425/**
7426 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7427 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7428 */
7429TEST_F(InputDispatcherMultiWindowOcclusionTests,
7430 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007431 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7432 "Window with input channel and NO_INPUT_CHANNEL",
7433 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007434
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007435 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007436 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7437 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7438
7439 PointF touchedPoint = {10, 10};
7440
Prabir Pradhan678438e2023-04-13 19:32:51 +00007441 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7442 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7443 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007444
7445 mNoInputWindow->assertNoEvents();
7446 mBottomWindow->assertNoEvents();
7447}
7448
Vishnu Nair958da932020-08-21 17:12:37 -07007449class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7450protected:
7451 std::shared_ptr<FakeApplicationHandle> mApp;
7452 sp<FakeWindowHandle> mWindow;
7453 sp<FakeWindowHandle> mMirror;
7454
7455 virtual void SetUp() override {
7456 InputDispatcherTest::SetUp();
7457 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007458 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7459 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7460 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007461 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7462 mWindow->setFocusable(true);
7463 mMirror->setFocusable(true);
7464 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7465 }
7466};
7467
7468TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7469 // Request focus on a mirrored window
7470 setFocusedWindow(mMirror);
7471
7472 // window gets focused
7473 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7475 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007476 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7477}
7478
7479// A focused & mirrored window remains focused only if the window and its mirror are both
7480// focusable.
7481TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7482 setFocusedWindow(mMirror);
7483
7484 // window gets focused
7485 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7487 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007488 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007489 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7490 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007491 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7492
7493 mMirror->setFocusable(false);
7494 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7495
7496 // window loses focus since one of the windows associated with the token in not focusable
7497 mWindow->consumeFocusEvent(false);
7498
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007499 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7500 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007501 mWindow->assertNoEvents();
7502}
7503
7504// A focused & mirrored window remains focused until the window and its mirror both become
7505// invisible.
7506TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7507 setFocusedWindow(mMirror);
7508
7509 // window gets focused
7510 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007511 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7512 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007513 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7515 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007516 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7517
7518 mMirror->setVisible(false);
7519 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7520
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007521 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7522 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007523 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7525 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007526 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7527
7528 mWindow->setVisible(false);
7529 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7530
7531 // window loses focus only after all windows associated with the token become invisible.
7532 mWindow->consumeFocusEvent(false);
7533
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007534 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7535 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007536 mWindow->assertNoEvents();
7537}
7538
7539// A focused & mirrored window remains focused until both windows are removed.
7540TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7541 setFocusedWindow(mMirror);
7542
7543 // window gets focused
7544 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007545 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7546 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007547 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007548 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7549 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007550 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7551
7552 // single window is removed but the window token remains focused
7553 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7554
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007555 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7556 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007557 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007558 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7559 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007560 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7561
7562 // Both windows are removed
7563 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7564 mWindow->consumeFocusEvent(false);
7565
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007566 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7567 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007568 mWindow->assertNoEvents();
7569}
7570
7571// Focus request can be pending until one window becomes visible.
7572TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7573 // Request focus on an invisible mirror.
7574 mWindow->setVisible(false);
7575 mMirror->setVisible(false);
7576 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7577 setFocusedWindow(mMirror);
7578
7579 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007581 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7582 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007583
7584 mMirror->setVisible(true);
7585 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7586
7587 // window gets focused
7588 mWindow->consumeFocusEvent(true);
7589 // window gets the pending key event
7590 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7591}
Prabir Pradhan99987712020-11-10 18:43:05 -08007592
7593class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7594protected:
7595 std::shared_ptr<FakeApplicationHandle> mApp;
7596 sp<FakeWindowHandle> mWindow;
7597 sp<FakeWindowHandle> mSecondWindow;
7598
7599 void SetUp() override {
7600 InputDispatcherTest::SetUp();
7601 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007602 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007603 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007604 mSecondWindow =
7605 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007606 mSecondWindow->setFocusable(true);
7607
7608 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7609 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7610
7611 setFocusedWindow(mWindow);
7612 mWindow->consumeFocusEvent(true);
7613 }
7614
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007615 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007616 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007617 }
7618
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007619 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7620 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007621 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007622 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7623 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007624 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007625 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007626 }
7627};
7628
7629TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7630 // Ensure that capture cannot be obtained for unfocused windows.
7631 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7632 mFakePolicy->assertSetPointerCaptureNotCalled();
7633 mSecondWindow->assertNoEvents();
7634
7635 // Ensure that capture can be enabled from the focus window.
7636 requestAndVerifyPointerCapture(mWindow, true);
7637
7638 // Ensure that capture cannot be disabled from a window that does not have capture.
7639 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7640 mFakePolicy->assertSetPointerCaptureNotCalled();
7641
7642 // Ensure that capture can be disabled from the window with capture.
7643 requestAndVerifyPointerCapture(mWindow, false);
7644}
7645
7646TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007647 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007648
7649 setFocusedWindow(mSecondWindow);
7650
7651 // Ensure that the capture disabled event was sent first.
7652 mWindow->consumeCaptureEvent(false);
7653 mWindow->consumeFocusEvent(false);
7654 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007655 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007656
7657 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007658 notifyPointerCaptureChanged({});
7659 notifyPointerCaptureChanged(request);
7660 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007661 mWindow->assertNoEvents();
7662 mSecondWindow->assertNoEvents();
7663 mFakePolicy->assertSetPointerCaptureNotCalled();
7664}
7665
7666TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007667 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007668
7669 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007670 notifyPointerCaptureChanged({});
7671 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007672
7673 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007674 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007675 mWindow->consumeCaptureEvent(false);
7676 mWindow->assertNoEvents();
7677}
7678
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007679TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7680 requestAndVerifyPointerCapture(mWindow, true);
7681
7682 // The first window loses focus.
7683 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007684 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007685 mWindow->consumeCaptureEvent(false);
7686
7687 // Request Pointer Capture from the second window before the notification from InputReader
7688 // arrives.
7689 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007690 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007691
7692 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007693 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007694
7695 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007696 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007697
7698 mSecondWindow->consumeFocusEvent(true);
7699 mSecondWindow->consumeCaptureEvent(true);
7700}
7701
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007702TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7703 // App repeatedly enables and disables capture.
7704 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7705 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7706 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7707 mFakePolicy->assertSetPointerCaptureCalled(false);
7708 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7709 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7710
7711 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7712 // first request is now stale, this should do nothing.
7713 notifyPointerCaptureChanged(firstRequest);
7714 mWindow->assertNoEvents();
7715
7716 // InputReader notifies that the second request was enabled.
7717 notifyPointerCaptureChanged(secondRequest);
7718 mWindow->consumeCaptureEvent(true);
7719}
7720
Prabir Pradhan7092e262022-05-03 16:51:09 +00007721TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7722 requestAndVerifyPointerCapture(mWindow, true);
7723
7724 // App toggles pointer capture off and on.
7725 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7726 mFakePolicy->assertSetPointerCaptureCalled(false);
7727
7728 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7729 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7730
7731 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7732 // preceding "disable" request.
7733 notifyPointerCaptureChanged(enableRequest);
7734
7735 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7736 // any notifications.
7737 mWindow->assertNoEvents();
7738}
7739
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007740class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7741protected:
7742 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007743
7744 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7745 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7746
7747 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7748 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7749
7750 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7751 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7752 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7753 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7754 MAXIMUM_OBSCURING_OPACITY);
7755
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007756 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007757 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007758 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007759
7760 sp<FakeWindowHandle> mTouchWindow;
7761
7762 virtual void SetUp() override {
7763 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007764 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007765 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7766 }
7767
7768 virtual void TearDown() override {
7769 InputDispatcherTest::TearDown();
7770 mTouchWindow.clear();
7771 }
7772
chaviw3277faf2021-05-19 16:45:23 -05007773 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
7774 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007775 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007776 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007777 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007778 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007779 return window;
7780 }
7781
7782 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
7783 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7784 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007785 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007786 // Generate an arbitrary PID based on the UID
7787 window->setOwnerInfo(1777 + (uid % 10000), uid);
7788 return window;
7789 }
7790
7791 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007792 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7793 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7794 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007795 }
7796};
7797
7798TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007799 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007800 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007801 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007802
7803 touch();
7804
7805 mTouchWindow->assertNoEvents();
7806}
7807
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007808TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007809 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7810 const sp<FakeWindowHandle>& w =
7811 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7812 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7813
7814 touch();
7815
7816 mTouchWindow->assertNoEvents();
7817}
7818
7819TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007820 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7821 const sp<FakeWindowHandle>& w =
7822 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7823 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7824
7825 touch();
7826
7827 w->assertNoEvents();
7828}
7829
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007830TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007831 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7832 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007833
7834 touch();
7835
7836 mTouchWindow->consumeAnyMotionDown();
7837}
7838
7839TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007840 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007841 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007842 w->setFrame(Rect(0, 0, 50, 50));
7843 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007844
7845 touch({PointF{100, 100}});
7846
7847 mTouchWindow->consumeAnyMotionDown();
7848}
7849
7850TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007851 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007852 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007853 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7854
7855 touch();
7856
7857 mTouchWindow->consumeAnyMotionDown();
7858}
7859
7860TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7861 const sp<FakeWindowHandle>& w =
7862 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7863 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007864
7865 touch();
7866
7867 mTouchWindow->consumeAnyMotionDown();
7868}
7869
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007870TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7871 const sp<FakeWindowHandle>& w =
7872 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7873 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7874
7875 touch();
7876
7877 w->assertNoEvents();
7878}
7879
7880/**
7881 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
7882 * inside) while letting them pass-through. Note that even though touch passes through the occluding
7883 * window, the occluding window will still receive ACTION_OUTSIDE event.
7884 */
7885TEST_F(InputDispatcherUntrustedTouchesTest,
7886 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
7887 const sp<FakeWindowHandle>& w =
7888 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007889 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007890 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7891
7892 touch();
7893
7894 w->consumeMotionOutside();
7895}
7896
7897TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
7898 const sp<FakeWindowHandle>& w =
7899 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007900 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007901 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7902
7903 touch();
7904
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007905 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007906}
7907
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007908TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007909 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007910 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7911 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007912 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7913
7914 touch();
7915
7916 mTouchWindow->consumeAnyMotionDown();
7917}
7918
7919TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
7920 const sp<FakeWindowHandle>& w =
7921 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7922 MAXIMUM_OBSCURING_OPACITY);
7923 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007924
7925 touch();
7926
7927 mTouchWindow->consumeAnyMotionDown();
7928}
7929
7930TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007931 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007932 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7933 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007934 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7935
7936 touch();
7937
7938 mTouchWindow->assertNoEvents();
7939}
7940
7941TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
7942 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
7943 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007944 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7945 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007946 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007947 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7948 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007949 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7950
7951 touch();
7952
7953 mTouchWindow->assertNoEvents();
7954}
7955
7956TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
7957 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
7958 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007959 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7960 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007961 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007962 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7963 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007964 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7965
7966 touch();
7967
7968 mTouchWindow->consumeAnyMotionDown();
7969}
7970
7971TEST_F(InputDispatcherUntrustedTouchesTest,
7972 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
7973 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007974 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7975 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007976 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007977 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7978 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007979 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
7980
7981 touch();
7982
7983 mTouchWindow->consumeAnyMotionDown();
7984}
7985
7986TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
7987 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007988 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7989 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007990 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007991 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7992 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007993 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007994
7995 touch();
7996
7997 mTouchWindow->assertNoEvents();
7998}
7999
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008000TEST_F(InputDispatcherUntrustedTouchesTest,
8001 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8002 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008003 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8004 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008005 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008006 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8007 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008008 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8009
8010 touch();
8011
8012 mTouchWindow->assertNoEvents();
8013}
8014
8015TEST_F(InputDispatcherUntrustedTouchesTest,
8016 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8017 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008018 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8019 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008020 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008021 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8022 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008023 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8024
8025 touch();
8026
8027 mTouchWindow->consumeAnyMotionDown();
8028}
8029
8030TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8031 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008032 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8033 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008034 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8035
8036 touch();
8037
8038 mTouchWindow->consumeAnyMotionDown();
8039}
8040
8041TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8042 const sp<FakeWindowHandle>& w =
8043 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
8044 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8045
8046 touch();
8047
8048 mTouchWindow->consumeAnyMotionDown();
8049}
8050
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008051TEST_F(InputDispatcherUntrustedTouchesTest,
8052 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8053 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8054 const sp<FakeWindowHandle>& w =
8055 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
8056 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8057
8058 touch();
8059
8060 mTouchWindow->assertNoEvents();
8061}
8062
8063TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8064 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8065 const sp<FakeWindowHandle>& w =
8066 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
8067 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8068
8069 touch();
8070
8071 mTouchWindow->consumeAnyMotionDown();
8072}
8073
8074TEST_F(InputDispatcherUntrustedTouchesTest,
8075 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8076 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8077 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008078 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8079 OPACITY_ABOVE_THRESHOLD);
8080 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8081
8082 touch();
8083
8084 mTouchWindow->consumeAnyMotionDown();
8085}
8086
8087TEST_F(InputDispatcherUntrustedTouchesTest,
8088 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8089 const sp<FakeWindowHandle>& w1 =
8090 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8091 OPACITY_BELOW_THRESHOLD);
8092 const sp<FakeWindowHandle>& w2 =
8093 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8094 OPACITY_BELOW_THRESHOLD);
8095 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8096
8097 touch();
8098
8099 mTouchWindow->assertNoEvents();
8100}
8101
8102/**
8103 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8104 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8105 * (which alone would result in allowing touches) does not affect the blocking behavior.
8106 */
8107TEST_F(InputDispatcherUntrustedTouchesTest,
8108 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8109 const sp<FakeWindowHandle>& wB =
8110 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8111 OPACITY_BELOW_THRESHOLD);
8112 const sp<FakeWindowHandle>& wC =
8113 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8114 OPACITY_BELOW_THRESHOLD);
8115 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8116
8117 touch();
8118
8119 mTouchWindow->assertNoEvents();
8120}
8121
8122/**
8123 * This test is testing that a window from a different UID but with same application token doesn't
8124 * block the touch. Apps can share the application token for close UI collaboration for example.
8125 */
8126TEST_F(InputDispatcherUntrustedTouchesTest,
8127 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8128 const sp<FakeWindowHandle>& w =
8129 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8130 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008131 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8132
8133 touch();
8134
8135 mTouchWindow->consumeAnyMotionDown();
8136}
8137
arthurhungb89ccb02020-12-30 16:19:01 +08008138class InputDispatcherDragTests : public InputDispatcherTest {
8139protected:
8140 std::shared_ptr<FakeApplicationHandle> mApp;
8141 sp<FakeWindowHandle> mWindow;
8142 sp<FakeWindowHandle> mSecondWindow;
8143 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008144 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008145 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8146 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008147
8148 void SetUp() override {
8149 InputDispatcherTest::SetUp();
8150 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008151 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008152 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008153
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008154 mSecondWindow =
8155 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008156 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008157
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008158 mSpyWindow =
8159 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008160 mSpyWindow->setSpy(true);
8161 mSpyWindow->setTrustedOverlay(true);
8162 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8163
arthurhungb89ccb02020-12-30 16:19:01 +08008164 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008165 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008166 }
8167
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008168 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8169 switch (fromSource) {
8170 case AINPUT_SOURCE_TOUCHSCREEN:
8171 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8172 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8173 ADISPLAY_ID_DEFAULT, {50, 50}))
8174 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8175 break;
8176 case AINPUT_SOURCE_STYLUS:
8177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8178 injectMotionEvent(
8179 mDispatcher,
8180 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8181 AINPUT_SOURCE_STYLUS)
8182 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008183 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008184 .x(50)
8185 .y(50))
8186 .build()));
8187 break;
8188 case AINPUT_SOURCE_MOUSE:
8189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8190 injectMotionEvent(
8191 mDispatcher,
8192 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8193 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8194 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008195 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008196 .x(50)
8197 .y(50))
8198 .build()));
8199 break;
8200 default:
8201 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8202 }
arthurhungb89ccb02020-12-30 16:19:01 +08008203
8204 // Window should receive motion event.
8205 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008206 // Spy window should also receive motion event
8207 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008208 }
8209
8210 // Start performing drag, we will create a drag window and transfer touch to it.
8211 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8212 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008213 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008214 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008215 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008216 }
arthurhungb89ccb02020-12-30 16:19:01 +08008217
8218 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008219 mDragWindow =
8220 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008221 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08008222 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008223 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008224
8225 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008226 bool transferred =
8227 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008228 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008229 if (transferred) {
8230 mWindow->consumeMotionCancel();
8231 mDragWindow->consumeMotionDown();
8232 }
8233 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008234 }
8235};
8236
8237TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008238 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +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 // Move back to original window.
8259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8260 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8261 ADISPLAY_ID_DEFAULT, {50, 50}))
8262 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8263 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8264 mWindow->consumeDragEvent(false, 50, 50);
8265 mSecondWindow->consumeDragEvent(true, -50, 50);
8266
8267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8268 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8269 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8270 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8271 mWindow->assertNoEvents();
8272 mSecondWindow->assertNoEvents();
8273}
8274
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008275TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008276 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008277
8278 // No cancel event after drag start
8279 mSpyWindow->assertNoEvents();
8280
8281 const MotionEvent secondFingerDownEvent =
8282 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8283 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008284 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8285 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008286 .build();
8287 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8288 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8289 InputEventInjectionSync::WAIT_FOR_RESULT))
8290 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8291
8292 // Receives cancel for first pointer after next pointer down
8293 mSpyWindow->consumeMotionCancel();
8294 mSpyWindow->consumeMotionDown();
8295
8296 mSpyWindow->assertNoEvents();
8297}
8298
arthurhungf452d0b2021-01-06 00:19:52 +08008299TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008300 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008301
8302 // Move on window.
8303 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8304 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8305 ADISPLAY_ID_DEFAULT, {50, 50}))
8306 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8307 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8308 mWindow->consumeDragEvent(false, 50, 50);
8309 mSecondWindow->assertNoEvents();
8310
8311 // Move to another window.
8312 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8313 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8314 ADISPLAY_ID_DEFAULT, {150, 50}))
8315 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8316 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8317 mWindow->consumeDragEvent(true, 150, 50);
8318 mSecondWindow->consumeDragEvent(false, 50, 50);
8319
8320 // drop to another window.
8321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8322 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8323 {150, 50}))
8324 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8325 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8326 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8327 mWindow->assertNoEvents();
8328 mSecondWindow->assertNoEvents();
8329}
8330
arthurhung6d4bed92021-03-17 11:59:33 +08008331TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008332 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008333
8334 // Move on window and keep button pressed.
8335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8336 injectMotionEvent(mDispatcher,
8337 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8338 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008339 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008340 .build()))
8341 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8342 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8343 mWindow->consumeDragEvent(false, 50, 50);
8344 mSecondWindow->assertNoEvents();
8345
8346 // Move to another window and release button, expect to drop item.
8347 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8348 injectMotionEvent(mDispatcher,
8349 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8350 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008351 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008352 .build()))
8353 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8354 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8355 mWindow->assertNoEvents();
8356 mSecondWindow->assertNoEvents();
8357 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8358
8359 // nothing to the window.
8360 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8361 injectMotionEvent(mDispatcher,
8362 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8363 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008364 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008365 .build()))
8366 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8367 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8368 mWindow->assertNoEvents();
8369 mSecondWindow->assertNoEvents();
8370}
8371
Arthur Hung54745652022-04-20 07:17:41 +00008372TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008373 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008374
8375 // Set second window invisible.
8376 mSecondWindow->setVisible(false);
8377 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8378
8379 // Move on window.
8380 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8381 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8382 ADISPLAY_ID_DEFAULT, {50, 50}))
8383 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8384 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8385 mWindow->consumeDragEvent(false, 50, 50);
8386 mSecondWindow->assertNoEvents();
8387
8388 // Move to another window.
8389 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8390 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8391 ADISPLAY_ID_DEFAULT, {150, 50}))
8392 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8393 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8394 mWindow->consumeDragEvent(true, 150, 50);
8395 mSecondWindow->assertNoEvents();
8396
8397 // drop to another window.
8398 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8399 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8400 {150, 50}))
8401 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8402 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8403 mFakePolicy->assertDropTargetEquals(nullptr);
8404 mWindow->assertNoEvents();
8405 mSecondWindow->assertNoEvents();
8406}
8407
Arthur Hung54745652022-04-20 07:17:41 +00008408TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008409 // Ensure window could track pointerIds if it didn't support split touch.
8410 mWindow->setPreventSplitting(true);
8411
Arthur Hung54745652022-04-20 07:17:41 +00008412 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8413 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8414 {50, 50}))
8415 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8416 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8417
8418 const MotionEvent secondFingerDownEvent =
8419 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8420 .displayId(ADISPLAY_ID_DEFAULT)
8421 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008422 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8423 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008424 .build();
8425 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8426 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8427 InputEventInjectionSync::WAIT_FOR_RESULT))
8428 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008429 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008430
8431 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008432 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008433}
8434
8435TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8436 // First down on second window.
8437 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8438 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8439 {150, 50}))
8440 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8441
8442 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8443
8444 // Second down on first window.
8445 const MotionEvent secondFingerDownEvent =
8446 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8447 .displayId(ADISPLAY_ID_DEFAULT)
8448 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008449 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8450 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008451 .build();
8452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8453 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8454 InputEventInjectionSync::WAIT_FOR_RESULT))
8455 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8456 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8457
8458 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008459 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008460
8461 // Move on window.
8462 const MotionEvent secondFingerMoveEvent =
8463 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8464 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008465 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8466 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008467 .build();
8468 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8469 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8470 InputEventInjectionSync::WAIT_FOR_RESULT));
8471 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8472 mWindow->consumeDragEvent(false, 50, 50);
8473 mSecondWindow->consumeMotionMove();
8474
8475 // Release the drag pointer should perform drop.
8476 const MotionEvent secondFingerUpEvent =
8477 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8478 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008479 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8480 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008481 .build();
8482 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8483 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8484 InputEventInjectionSync::WAIT_FOR_RESULT));
8485 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8486 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
8487 mWindow->assertNoEvents();
8488 mSecondWindow->consumeMotionMove();
8489}
8490
Arthur Hung3915c1f2022-05-31 07:17:17 +00008491TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008492 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008493
8494 // Update window of second display.
8495 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008496 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008497 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8498
8499 // Let second display has a touch state.
8500 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8501 injectMotionEvent(mDispatcher,
8502 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8503 AINPUT_SOURCE_TOUCHSCREEN)
8504 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008505 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008506 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008507 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008508 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008509 // Update window again.
8510 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8511
8512 // Move on window.
8513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8514 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8515 ADISPLAY_ID_DEFAULT, {50, 50}))
8516 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8517 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8518 mWindow->consumeDragEvent(false, 50, 50);
8519 mSecondWindow->assertNoEvents();
8520
8521 // Move to another window.
8522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8523 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8524 ADISPLAY_ID_DEFAULT, {150, 50}))
8525 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8526 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8527 mWindow->consumeDragEvent(true, 150, 50);
8528 mSecondWindow->consumeDragEvent(false, 50, 50);
8529
8530 // drop to another window.
8531 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8532 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8533 {150, 50}))
8534 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8535 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8536 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8537 mWindow->assertNoEvents();
8538 mSecondWindow->assertNoEvents();
8539}
8540
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008541TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8542 startDrag(true, AINPUT_SOURCE_MOUSE);
8543 // Move on window.
8544 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8545 injectMotionEvent(mDispatcher,
8546 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8547 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8548 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008549 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008550 .x(50)
8551 .y(50))
8552 .build()))
8553 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8554 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8555 mWindow->consumeDragEvent(false, 50, 50);
8556 mSecondWindow->assertNoEvents();
8557
8558 // Move to another window.
8559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8560 injectMotionEvent(mDispatcher,
8561 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8562 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8563 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008564 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008565 .x(150)
8566 .y(50))
8567 .build()))
8568 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8569 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8570 mWindow->consumeDragEvent(true, 150, 50);
8571 mSecondWindow->consumeDragEvent(false, 50, 50);
8572
8573 // drop to another window.
8574 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8575 injectMotionEvent(mDispatcher,
8576 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8577 .buttonState(0)
8578 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008579 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008580 .x(150)
8581 .y(50))
8582 .build()))
8583 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8584 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8585 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8586 mWindow->assertNoEvents();
8587 mSecondWindow->assertNoEvents();
8588}
8589
Vishnu Nair062a8672021-09-03 16:07:44 -07008590class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8591
8592TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8593 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008594 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8595 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008596 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008597 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8598 window->setFocusable(true);
8599 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8600 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008601 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008602
8603 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008604 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008605 window->assertNoEvents();
8606
Prabir Pradhan678438e2023-04-13 19:32:51 +00008607 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8608 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008609 window->assertNoEvents();
8610
8611 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008612 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008613 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8614
Prabir Pradhan678438e2023-04-13 19:32:51 +00008615 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008616 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8617
Prabir Pradhan678438e2023-04-13 19:32:51 +00008618 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8619 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008620 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8621 window->assertNoEvents();
8622}
8623
8624TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8625 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8626 std::make_shared<FakeApplicationHandle>();
8627 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008628 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8629 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008630 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8631 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008632 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008633 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008634 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8635 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008636 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008637 window->setOwnerInfo(222, 222);
8638 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8639 window->setFocusable(true);
8640 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8641 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008642 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008643
8644 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008645 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008646 window->assertNoEvents();
8647
Prabir Pradhan678438e2023-04-13 19:32:51 +00008648 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8649 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008650 window->assertNoEvents();
8651
8652 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008653 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008654 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8655
Prabir Pradhan678438e2023-04-13 19:32:51 +00008656 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008657 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8658
Prabir Pradhan678438e2023-04-13 19:32:51 +00008659 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8660 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008661 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8662 window->assertNoEvents();
8663}
8664
8665TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8666 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8667 std::make_shared<FakeApplicationHandle>();
8668 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008669 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8670 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008671 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8672 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008673 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008674 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008675 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8676 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008677 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008678 window->setOwnerInfo(222, 222);
8679 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8680 window->setFocusable(true);
8681 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8682 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008683 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008684
8685 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008686 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008687 window->assertNoEvents();
8688
Prabir Pradhan678438e2023-04-13 19:32:51 +00008689 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8690 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008691 window->assertNoEvents();
8692
8693 // When the window is no longer obscured because it went on top, it should get input
8694 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8695
Prabir Pradhan678438e2023-04-13 19:32:51 +00008696 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008697 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8698
Prabir Pradhan678438e2023-04-13 19:32:51 +00008699 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8700 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008701 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8702 window->assertNoEvents();
8703}
8704
Antonio Kantekf16f2832021-09-28 04:39:20 +00008705class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8706protected:
8707 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008708 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008709 sp<FakeWindowHandle> mWindow;
8710 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008711 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008712
8713 void SetUp() override {
8714 InputDispatcherTest::SetUp();
8715
8716 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008717 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008718 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008719 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008720 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008721 mSecondWindow =
8722 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008723 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008724 mThirdWindow =
8725 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8726 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8727 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008728
8729 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008730 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8731 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8732 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008733 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008734
Antonio Kantek15beb512022-06-13 22:35:41 +00008735 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008736 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008737 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008738 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8739 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008740 mThirdWindow->assertNoEvents();
8741 }
8742
8743 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8744 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008745 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008746 SECOND_DISPLAY_ID)) {
8747 mWindow->assertNoEvents();
8748 mSecondWindow->assertNoEvents();
8749 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008750 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008751 }
8752
Antonio Kantek15beb512022-06-13 22:35:41 +00008753 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid,
8754 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008755 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8756 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008757 mWindow->consumeTouchModeEvent(inTouchMode);
8758 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008759 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008760 }
8761};
8762
Antonio Kantek26defcf2022-02-08 01:12:27 +00008763TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008764 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008765 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8766 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008767 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008768}
8769
Antonio Kantek26defcf2022-02-08 01:12:27 +00008770TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8771 const WindowInfo& windowInfo = *mWindow->getInfo();
8772 int32_t ownerPid = windowInfo.ownerPid;
8773 int32_t ownerUid = windowInfo.ownerUid;
8774 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
8775 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008776 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008777 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008778 mWindow->assertNoEvents();
8779 mSecondWindow->assertNoEvents();
8780}
8781
8782TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8783 const WindowInfo& windowInfo = *mWindow->getInfo();
8784 int32_t ownerPid = windowInfo.ownerPid;
8785 int32_t ownerUid = windowInfo.ownerUid;
8786 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
Antonio Kantek15beb512022-06-13 22:35:41 +00008787 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008788 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008789}
8790
Antonio Kantekf16f2832021-09-28 04:39:20 +00008791TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008792 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008793 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8794 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008795 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008796 mWindow->assertNoEvents();
8797 mSecondWindow->assertNoEvents();
8798}
8799
Antonio Kantek15beb512022-06-13 22:35:41 +00008800TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8801 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8802 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8803 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008804 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008805 mWindow->assertNoEvents();
8806 mSecondWindow->assertNoEvents();
8807 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8808}
8809
Antonio Kantek48710e42022-03-24 14:19:30 -07008810TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8811 // Interact with the window first.
8812 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8813 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8814 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8815
8816 // Then remove focus.
8817 mWindow->setFocusable(false);
8818 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8819
8820 // Assert that caller can switch touch mode by owning one of the last interacted window.
8821 const WindowInfo& windowInfo = *mWindow->getInfo();
8822 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8823 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008824 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008825}
8826
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008827class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8828public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008829 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008830 std::shared_ptr<FakeApplicationHandle> application =
8831 std::make_shared<FakeApplicationHandle>();
8832 std::string name = "Fake Spy ";
8833 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008834 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8835 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008836 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008837 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008838 return spy;
8839 }
8840
8841 sp<FakeWindowHandle> createForeground() {
8842 std::shared_ptr<FakeApplicationHandle> application =
8843 std::make_shared<FakeApplicationHandle>();
8844 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008845 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8846 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008847 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008848 return window;
8849 }
8850
8851private:
8852 int mSpyCount{0};
8853};
8854
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008855using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008856/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008857 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8858 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008859TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8860 ScopedSilentDeath _silentDeath;
8861
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008862 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008863 spy->setTrustedOverlay(false);
8864 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8865 ".* not a trusted overlay");
8866}
8867
8868/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008869 * Input injection into a display with a spy window but no foreground windows should succeed.
8870 */
8871TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008872 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008873 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
8874
8875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8876 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8877 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8878 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8879}
8880
8881/**
8882 * Verify the order in which different input windows receive events. The touched foreground window
8883 * (if there is one) should always receive the event first. When there are multiple spy windows, the
8884 * spy windows will receive the event according to their Z-order, where the top-most spy window will
8885 * receive events before ones belows it.
8886 *
8887 * Here, we set up a scenario with four windows in the following Z order from the top:
8888 * spy1, spy2, window, spy3.
8889 * We then inject an event and verify that the foreground "window" receives it first, followed by
8890 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
8891 * window.
8892 */
8893TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
8894 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008895 auto spy1 = createSpy();
8896 auto spy2 = createSpy();
8897 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008898 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
8899 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
8900 const size_t numChannels = channels.size();
8901
Michael Wright8e9a8562022-02-09 13:44:29 +00008902 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008903 if (!epollFd.ok()) {
8904 FAIL() << "Failed to create epoll fd";
8905 }
8906
8907 for (size_t i = 0; i < numChannels; i++) {
8908 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
8909 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
8910 FAIL() << "Failed to add fd to epoll";
8911 }
8912 }
8913
8914 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8915 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8916 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8917
8918 std::vector<size_t> eventOrder;
8919 std::vector<struct epoll_event> events(numChannels);
8920 for (;;) {
8921 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
8922 (100ms).count());
8923 if (nFds < 0) {
8924 FAIL() << "Failed to call epoll_wait";
8925 }
8926 if (nFds == 0) {
8927 break; // epoll_wait timed out
8928 }
8929 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07008930 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07008931 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008932 channels[i]->consumeMotionDown();
8933 }
8934 }
8935
8936 // Verify the order in which the events were received.
8937 EXPECT_EQ(3u, eventOrder.size());
8938 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
8939 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
8940 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
8941}
8942
8943/**
8944 * A spy window using the NOT_TOUCHABLE flag does not receive events.
8945 */
8946TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
8947 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008948 auto spy = createSpy();
8949 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008950 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8951
8952 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8953 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8954 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8955 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8956 spy->assertNoEvents();
8957}
8958
8959/**
8960 * A spy window will only receive gestures that originate within its touchable region. Gestures that
8961 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
8962 * to the window.
8963 */
8964TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
8965 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008966 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008967 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
8968 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8969
8970 // Inject an event outside the spy window's touchable region.
8971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8972 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8973 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8974 window->consumeMotionDown();
8975 spy->assertNoEvents();
8976 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8977 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8978 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8979 window->consumeMotionUp();
8980 spy->assertNoEvents();
8981
8982 // Inject an event inside the spy window's touchable region.
8983 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8984 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8985 {5, 10}))
8986 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8987 window->consumeMotionDown();
8988 spy->consumeMotionDown();
8989}
8990
8991/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008992 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008993 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008994 */
8995TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
8996 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008997 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008998 auto spy = createSpy();
8999 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009000 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009001 spy->setFrame(Rect{0, 0, 20, 20});
9002 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9003
9004 // Inject an event outside the spy window's frame and touchable region.
9005 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009006 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9007 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009008 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9009 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009010 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009011}
9012
9013/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009014 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9015 * pointers that are down within its bounds.
9016 */
9017TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9018 auto windowLeft = createForeground();
9019 windowLeft->setFrame({0, 0, 100, 200});
9020 auto windowRight = createForeground();
9021 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009022 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009023 spy->setFrame({0, 0, 200, 200});
9024 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
9025
9026 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9027 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9028 {50, 50}))
9029 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9030 windowLeft->consumeMotionDown();
9031 spy->consumeMotionDown();
9032
9033 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009034 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009035 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009036 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9037 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009038 .build();
9039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9040 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9041 InputEventInjectionSync::WAIT_FOR_RESULT))
9042 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9043 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009044 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009045}
9046
9047/**
9048 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9049 * the spy should receive the second pointer with ACTION_DOWN.
9050 */
9051TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9052 auto window = createForeground();
9053 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009054 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009055 spyRight->setFrame({100, 0, 200, 200});
9056 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
9057
9058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9059 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9060 {50, 50}))
9061 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9062 window->consumeMotionDown();
9063 spyRight->assertNoEvents();
9064
9065 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009066 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009067 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009068 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9069 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009070 .build();
9071 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9072 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9073 InputEventInjectionSync::WAIT_FOR_RESULT))
9074 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009075 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009076 spyRight->consumeMotionDown();
9077}
9078
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009079/**
9080 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9081 * windows should be allowed to control split touch.
9082 */
9083TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009084 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009085 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009086 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009087 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009088
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009089 auto window = createForeground();
9090 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009091
9092 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9093
9094 // First finger down, no window touched.
9095 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9096 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9097 {100, 200}))
9098 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9099 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9100 window->assertNoEvents();
9101
9102 // Second finger down on window, the window should receive touch down.
9103 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009104 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009105 .displayId(ADISPLAY_ID_DEFAULT)
9106 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009107 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9108 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009109 .build();
9110 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9111 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9112 InputEventInjectionSync::WAIT_FOR_RESULT))
9113 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9114
9115 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009116 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009117}
9118
9119/**
9120 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9121 * do not receive key events.
9122 */
9123TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009124 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009125 spy->setFocusable(false);
9126
9127 auto window = createForeground();
9128 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9129 setFocusedWindow(window);
9130 window->consumeFocusEvent(true);
9131
9132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
9133 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9134 window->consumeKeyDown(ADISPLAY_ID_NONE);
9135
9136 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
9137 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9138 window->consumeKeyUp(ADISPLAY_ID_NONE);
9139
9140 spy->assertNoEvents();
9141}
9142
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009143using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9144
9145/**
9146 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9147 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9148 */
9149TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9150 auto window = createForeground();
9151 auto spy1 = createSpy();
9152 auto spy2 = createSpy();
9153 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
9154
9155 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9156 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9157 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9158 window->consumeMotionDown();
9159 spy1->consumeMotionDown();
9160 spy2->consumeMotionDown();
9161
9162 // Pilfer pointers from the second spy window.
9163 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9164 spy2->assertNoEvents();
9165 spy1->consumeMotionCancel();
9166 window->consumeMotionCancel();
9167
9168 // The rest of the gesture should only be sent to the second spy window.
9169 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9170 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9171 ADISPLAY_ID_DEFAULT))
9172 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9173 spy2->consumeMotionMove();
9174 spy1->assertNoEvents();
9175 window->assertNoEvents();
9176}
9177
9178/**
9179 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9180 * in the middle of the gesture.
9181 */
9182TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9183 auto window = createForeground();
9184 auto spy = createSpy();
9185 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9186
9187 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9188 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9189 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9190 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9191 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9192
9193 window->releaseChannel();
9194
9195 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9196
9197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9198 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9199 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9200 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9201}
9202
9203/**
9204 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9205 * the spy, but not to any other windows.
9206 */
9207TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9208 auto spy = createSpy();
9209 auto window = createForeground();
9210
9211 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9212
9213 // First finger down on the window and the spy.
9214 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9215 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9216 {100, 200}))
9217 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9218 spy->consumeMotionDown();
9219 window->consumeMotionDown();
9220
9221 // Spy window pilfers the pointers.
9222 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9223 window->consumeMotionCancel();
9224
9225 // Second finger down on the window and spy, but the window should not receive the pointer down.
9226 const MotionEvent secondFingerDownEvent =
9227 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9228 .displayId(ADISPLAY_ID_DEFAULT)
9229 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009230 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9231 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009232 .build();
9233 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9234 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9235 InputEventInjectionSync::WAIT_FOR_RESULT))
9236 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9237
Harry Cutts33476232023-01-30 19:57:29 +00009238 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009239
9240 // Third finger goes down outside all windows, so injection should fail.
9241 const MotionEvent thirdFingerDownEvent =
9242 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9243 .displayId(ADISPLAY_ID_DEFAULT)
9244 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009245 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9246 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9247 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009248 .build();
9249 ASSERT_EQ(InputEventInjectionResult::FAILED,
9250 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9251 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009252 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009253
9254 spy->assertNoEvents();
9255 window->assertNoEvents();
9256}
9257
9258/**
9259 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9260 */
9261TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9262 auto spy = createSpy();
9263 spy->setFrame(Rect(0, 0, 100, 100));
9264 auto window = createForeground();
9265 window->setFrame(Rect(0, 0, 200, 200));
9266
9267 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9268
9269 // First finger down on the window only
9270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9271 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9272 {150, 150}))
9273 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9274 window->consumeMotionDown();
9275
9276 // Second finger down on the spy and window
9277 const MotionEvent secondFingerDownEvent =
9278 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9279 .displayId(ADISPLAY_ID_DEFAULT)
9280 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009281 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9282 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009283 .build();
9284 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9285 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9286 InputEventInjectionSync::WAIT_FOR_RESULT))
9287 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9288 spy->consumeMotionDown();
9289 window->consumeMotionPointerDown(1);
9290
9291 // Third finger down on the spy and window
9292 const MotionEvent thirdFingerDownEvent =
9293 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9294 .displayId(ADISPLAY_ID_DEFAULT)
9295 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009296 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9297 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9298 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009299 .build();
9300 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9301 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9302 InputEventInjectionSync::WAIT_FOR_RESULT))
9303 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9304 spy->consumeMotionPointerDown(1);
9305 window->consumeMotionPointerDown(2);
9306
9307 // Spy window pilfers the pointers.
9308 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9309 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9310 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9311
9312 spy->assertNoEvents();
9313 window->assertNoEvents();
9314}
9315
9316/**
9317 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9318 * other windows should be canceled. If this results in the cancellation of all pointers for some
9319 * window, then that window should receive ACTION_CANCEL.
9320 */
9321TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9322 auto spy = createSpy();
9323 spy->setFrame(Rect(0, 0, 100, 100));
9324 auto window = createForeground();
9325 window->setFrame(Rect(0, 0, 200, 200));
9326
9327 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9328
9329 // First finger down on both spy and window
9330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9331 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9332 {10, 10}))
9333 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9334 window->consumeMotionDown();
9335 spy->consumeMotionDown();
9336
9337 // Second finger down on the spy and window
9338 const MotionEvent secondFingerDownEvent =
9339 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9340 .displayId(ADISPLAY_ID_DEFAULT)
9341 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009342 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9343 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009344 .build();
9345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9346 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9347 InputEventInjectionSync::WAIT_FOR_RESULT))
9348 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9349 spy->consumeMotionPointerDown(1);
9350 window->consumeMotionPointerDown(1);
9351
9352 // Spy window pilfers the pointers.
9353 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9354 window->consumeMotionCancel();
9355
9356 spy->assertNoEvents();
9357 window->assertNoEvents();
9358}
9359
9360/**
9361 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9362 * be sent to other windows
9363 */
9364TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9365 auto spy = createSpy();
9366 spy->setFrame(Rect(0, 0, 100, 100));
9367 auto window = createForeground();
9368 window->setFrame(Rect(0, 0, 200, 200));
9369
9370 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9371
9372 // First finger down on both window and spy
9373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9374 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9375 {10, 10}))
9376 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9377 window->consumeMotionDown();
9378 spy->consumeMotionDown();
9379
9380 // Spy window pilfers the pointers.
9381 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9382 window->consumeMotionCancel();
9383
9384 // Second finger down on the window only
9385 const MotionEvent secondFingerDownEvent =
9386 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9387 .displayId(ADISPLAY_ID_DEFAULT)
9388 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009389 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9390 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009391 .build();
9392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9393 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9394 InputEventInjectionSync::WAIT_FOR_RESULT))
9395 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9396 window->consumeMotionDown();
9397 window->assertNoEvents();
9398
9399 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9400 spy->consumeMotionMove();
9401 spy->assertNoEvents();
9402}
9403
Prabir Pradhand65552b2021-10-07 11:23:50 -07009404class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9405public:
9406 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9407 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9408 std::make_shared<FakeApplicationHandle>();
9409 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009410 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9411 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009412 overlay->setFocusable(false);
9413 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009414 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009415 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009416 overlay->setTrustedOverlay(true);
9417
9418 std::shared_ptr<FakeApplicationHandle> application =
9419 std::make_shared<FakeApplicationHandle>();
9420 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009421 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9422 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009423 window->setFocusable(true);
9424 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009425
9426 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9427 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9428 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009429 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009430 return {std::move(overlay), std::move(window)};
9431 }
9432
9433 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009434 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009435 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009436 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009437 }
9438
9439 void sendStylusEvent(int32_t action) {
9440 NotifyMotionArgs motionArgs =
9441 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9442 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009443 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009444 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009445 }
9446};
9447
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009448using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9449
9450TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
9451 ScopedSilentDeath _silentDeath;
9452
Prabir Pradhand65552b2021-10-07 11:23:50 -07009453 auto [overlay, window] = setupStylusOverlayScenario();
9454 overlay->setTrustedOverlay(false);
9455 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9456 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9457 ".* not a trusted overlay");
9458}
9459
9460TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9461 auto [overlay, window] = setupStylusOverlayScenario();
9462 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9463
9464 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9465 overlay->consumeMotionDown();
9466 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9467 overlay->consumeMotionUp();
9468
9469 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9470 window->consumeMotionDown();
9471 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9472 window->consumeMotionUp();
9473
9474 overlay->assertNoEvents();
9475 window->assertNoEvents();
9476}
9477
9478TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9479 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009480 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009481 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9482
9483 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9484 overlay->consumeMotionDown();
9485 window->consumeMotionDown();
9486 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9487 overlay->consumeMotionUp();
9488 window->consumeMotionUp();
9489
9490 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9491 window->consumeMotionDown();
9492 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9493 window->consumeMotionUp();
9494
9495 overlay->assertNoEvents();
9496 window->assertNoEvents();
9497}
9498
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009499/**
9500 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9501 * The scenario is as follows:
9502 * - The stylus interceptor overlay is configured as a spy window.
9503 * - The stylus interceptor spy receives the start of a new stylus gesture.
9504 * - It pilfers pointers and then configures itself to no longer be a spy.
9505 * - The stylus interceptor continues to receive the rest of the gesture.
9506 */
9507TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9508 auto [overlay, window] = setupStylusOverlayScenario();
9509 overlay->setSpy(true);
9510 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9511
9512 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9513 overlay->consumeMotionDown();
9514 window->consumeMotionDown();
9515
9516 // The interceptor pilfers the pointers.
9517 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9518 window->consumeMotionCancel();
9519
9520 // The interceptor configures itself so that it is no longer a spy.
9521 overlay->setSpy(false);
9522 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9523
9524 // It continues to receive the rest of the stylus gesture.
9525 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9526 overlay->consumeMotionMove();
9527 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9528 overlay->consumeMotionUp();
9529
9530 window->assertNoEvents();
9531}
9532
Prabir Pradhan5735a322022-04-11 17:23:34 +00009533struct User {
9534 int32_t mPid;
9535 int32_t mUid;
9536 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9537 std::unique_ptr<InputDispatcher>& mDispatcher;
9538
9539 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
9540 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9541
9542 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9543 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9544 ADISPLAY_ID_DEFAULT, {100, 200},
9545 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9546 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9547 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9548 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9549 }
9550
9551 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009552 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009553 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009554 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009555 mPolicyFlags);
9556 }
9557
9558 sp<FakeWindowHandle> createWindow() const {
9559 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9560 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009561 sp<FakeWindowHandle> window =
9562 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9563 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009564 window->setOwnerInfo(mPid, mUid);
9565 return window;
9566 }
9567};
9568
9569using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9570
9571TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
9572 auto owner = User(mDispatcher, 10, 11);
9573 auto window = owner.createWindow();
9574 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9575
9576 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9577 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9578 window->consumeMotionDown();
9579
9580 setFocusedWindow(window);
9581 window->consumeFocusEvent(true);
9582
9583 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9584 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9585 window->consumeKeyDown(ADISPLAY_ID_NONE);
9586}
9587
9588TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
9589 auto owner = User(mDispatcher, 10, 11);
9590 auto window = owner.createWindow();
9591 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9592
9593 auto rando = User(mDispatcher, 20, 21);
9594 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9595 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9596
9597 setFocusedWindow(window);
9598 window->consumeFocusEvent(true);
9599
9600 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9601 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9602 window->assertNoEvents();
9603}
9604
9605TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
9606 auto owner = User(mDispatcher, 10, 11);
9607 auto window = owner.createWindow();
9608 auto spy = owner.createWindow();
9609 spy->setSpy(true);
9610 spy->setTrustedOverlay(true);
9611 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9612
9613 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9614 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9615 spy->consumeMotionDown();
9616 window->consumeMotionDown();
9617}
9618
9619TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
9620 auto owner = User(mDispatcher, 10, 11);
9621 auto window = owner.createWindow();
9622
9623 auto rando = User(mDispatcher, 20, 21);
9624 auto randosSpy = rando.createWindow();
9625 randosSpy->setSpy(true);
9626 randosSpy->setTrustedOverlay(true);
9627 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9628
9629 // The event is targeted at owner's window, so injection should succeed, but the spy should
9630 // not receive the event.
9631 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9632 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9633 randosSpy->assertNoEvents();
9634 window->consumeMotionDown();
9635}
9636
9637TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
9638 auto owner = User(mDispatcher, 10, 11);
9639 auto window = owner.createWindow();
9640
9641 auto rando = User(mDispatcher, 20, 21);
9642 auto randosSpy = rando.createWindow();
9643 randosSpy->setSpy(true);
9644 randosSpy->setTrustedOverlay(true);
9645 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9646
9647 // A user that has injection permission can inject into any window.
9648 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9649 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9650 ADISPLAY_ID_DEFAULT));
9651 randosSpy->consumeMotionDown();
9652 window->consumeMotionDown();
9653
9654 setFocusedWindow(randosSpy);
9655 randosSpy->consumeFocusEvent(true);
9656
9657 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9658 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9659 window->assertNoEvents();
9660}
9661
9662TEST_F(InputDispatcherTargetedInjectionTest, CanGenerateActionOutsideToOtherUids) {
9663 auto owner = User(mDispatcher, 10, 11);
9664 auto window = owner.createWindow();
9665
9666 auto rando = User(mDispatcher, 20, 21);
9667 auto randosWindow = rando.createWindow();
9668 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9669 randosWindow->setWatchOutsideTouch(true);
9670 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9671
9672 // We allow generation of ACTION_OUTSIDE events into windows owned by different uids.
9673 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9674 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9675 window->consumeMotionDown();
9676 randosWindow->consumeMotionOutside();
9677}
9678
Garfield Tane84e6f92019-08-29 17:28:41 -07009679} // namespace android::inputdispatcher