blob: adae009d71bb949449bb175de70fc552e519140f [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 Pradhan8ede1d12023-05-08 19:37:44 +000018#include "../BlockingQueue.h"
Prabir Pradhan9205e422023-05-16 20:06:13 +000019#include "EventBuilders.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080020
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070021#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080022#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080023#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070024#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070025#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000026#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080027#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080028#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100029#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080030#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080031#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100032
Garfield Tan1c7bc862020-01-28 13:24:04 -080033#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080034#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070035#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080036#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080037#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080038
Garfield Tan1c7bc862020-01-28 13:24:04 -080039using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050040using android::gui::FocusRequest;
41using android::gui::TouchOcclusionMode;
42using android::gui::WindowInfo;
43using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080044using android::os::InputEventInjectionResult;
45using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080046
Garfield Tane84e6f92019-08-29 17:28:41 -070047namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080048
Dominik Laskowski2f01d772022-03-23 16:01:29 -070049using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080050using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070051
Michael Wrightd02c5b62014-02-10 15:10:22 -080052// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000053static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080054
55// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000056static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080057static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080058
Jeff Brownf086ddb2014-02-11 14:28:48 -080059// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000060static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
61static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080062
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000063// Ensure common actions are interchangeable between keys and motions for convenience.
64static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
65static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080066static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
67static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
68static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
69static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070070static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080071static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080072static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080073static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080074/**
75 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
76 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
77 * index 0) is the new pointer going down. The same pointer could have been placed at a different
78 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
79 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
80 * pointer id=0 leaves but the pointer id=1 remains.
81 */
82static constexpr int32_t POINTER_0_DOWN =
83 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080084static constexpr int32_t POINTER_1_DOWN =
85 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000086static constexpr int32_t POINTER_2_DOWN =
87 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000088static constexpr int32_t POINTER_3_DOWN =
89 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000090static constexpr int32_t POINTER_0_UP =
91 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080092static constexpr int32_t POINTER_1_UP =
93 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +000094static constexpr int32_t POINTER_2_UP =
95 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080096
Antonio Kantek15beb512022-06-13 22:35:41 +000097// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhan5735a322022-04-11 17:23:34 +000098static constexpr int32_t WINDOW_PID = 999;
99static constexpr int32_t WINDOW_UID = 1001;
100
Antonio Kantek15beb512022-06-13 22:35:41 +0000101// The default pid and uid for the windows created on the secondary display by the test.
102static constexpr int32_t SECONDARY_WINDOW_PID = 1010;
103static constexpr int32_t SECONDARY_WINDOW_UID = 1012;
104
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000105// An arbitrary pid of the gesture monitor window
106static constexpr int32_t MONITOR_PID = 2001;
107
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800108static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
109
Arthur Hungc539dbb2022-12-08 07:45:36 +0000110static constexpr int expectedWallpaperFlags =
111 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
112
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800113using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
114
chaviwd1c23182019-12-20 18:44:56 -0800115struct PointF {
116 float x;
117 float y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800118 auto operator<=>(const PointF&) const = default;
chaviwd1c23182019-12-20 18:44:56 -0800119};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800120
Gang Wang342c9272020-01-13 13:15:04 -0500121/**
122 * Return a DOWN key event with KEYCODE_A.
123 */
124static KeyEvent getTestKeyEvent() {
125 KeyEvent event;
126
Garfield Tanfbe732e2020-01-24 11:26:14 -0800127 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
128 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
129 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500130 return event;
131}
132
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000133static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
134 ASSERT_EQ(expectedAction, receivedAction)
135 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
136 << MotionEvent::actionToString(receivedAction);
137}
138
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800139MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") {
140 bool matches = action == arg.getAction();
141 if (!matches) {
142 *result_listener << "expected action " << MotionEvent::actionToString(action)
143 << ", but got " << MotionEvent::actionToString(arg.getAction());
144 }
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800145 if (action == AMOTION_EVENT_ACTION_DOWN) {
146 if (!matches) {
147 *result_listener << "; ";
148 }
149 *result_listener << "downTime should match eventTime for ACTION_DOWN events";
150 matches &= arg.getDownTime() == arg.getEventTime();
151 }
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800152 if (action == AMOTION_EVENT_ACTION_CANCEL) {
153 if (!matches) {
154 *result_listener << "; ";
155 }
156 *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set";
157 matches &= (arg.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
158 }
159 return matches;
160}
161
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800162MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
163 return arg.getDownTime() == downTime;
164}
165
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800166MATCHER_P(WithDisplayId, displayId, "InputEvent with specified displayId") {
167 return arg.getDisplayId() == displayId;
168}
169
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800170MATCHER_P(WithDeviceId, deviceId, "InputEvent with specified deviceId") {
171 return arg.getDeviceId() == deviceId;
172}
173
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800174MATCHER_P(WithSource, source, "InputEvent with specified source") {
175 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
176 << inputEventSourceToString(arg.getSource());
177 return arg.getSource() == source;
178}
179
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800180MATCHER_P(WithFlags, flags, "InputEvent with specified flags") {
181 return arg.getFlags() == flags;
182}
183
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800184MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
185 if (arg.getPointerCount() != 1) {
186 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
187 return false;
188 }
Harry Cutts33476232023-01-30 19:57:29 +0000189 return arg.getX(/*pointerIndex=*/0) == x && arg.getY(/*pointerIndex=*/0) == y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800190}
191
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800192MATCHER_P(WithPointerCount, pointerCount, "MotionEvent with specified number of pointers") {
193 return arg.getPointerCount() == pointerCount;
194}
195
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800196MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
197 // Build a map for the received pointers, by pointer id
198 std::map<int32_t /*pointerId*/, PointF> actualPointers;
199 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
200 const int32_t pointerId = arg.getPointerId(pointerIndex);
201 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
202 }
203 return pointers == actualPointers;
204}
205
Michael Wrightd02c5b62014-02-10 15:10:22 -0800206// --- FakeInputDispatcherPolicy ---
207
208class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
209 InputDispatcherConfiguration mConfig;
210
Prabir Pradhanedd96402022-02-15 01:46:16 -0800211 using AnrResult = std::pair<sp<IBinder>, int32_t /*pid*/>;
212
Michael Wrightd02c5b62014-02-10 15:10:22 -0800213public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000214 FakeInputDispatcherPolicy() = default;
215 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800216
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800217 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700218 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700219 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700220 EXPECT_EQ(event.getDisplayId(), args.displayId);
221
222 const auto& keyEvent = static_cast<const KeyEvent&>(event);
223 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
224 EXPECT_EQ(keyEvent.getAction(), args.action);
225 });
Jackal Guof9696682018-10-05 12:23:23 +0800226 }
227
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700228 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
229 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700230 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700231 EXPECT_EQ(event.getDisplayId(), args.displayId);
232
233 const auto& motionEvent = static_cast<const MotionEvent&>(event);
234 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
235 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000236 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
237 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
238 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
239 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700240 });
Jackal Guof9696682018-10-05 12:23:23 +0800241 }
242
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700243 void assertFilterInputEventWasNotCalled() {
244 std::scoped_lock lock(mLock);
245 ASSERT_EQ(nullptr, mFilteredEvent);
246 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800247
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800248 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700249 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800250 ASSERT_TRUE(mConfigurationChangedTime)
251 << "Timed out waiting for configuration changed call";
252 ASSERT_EQ(*mConfigurationChangedTime, when);
253 mConfigurationChangedTime = std::nullopt;
254 }
255
256 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700257 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800258 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800259 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800260 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
261 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
262 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
263 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
264 mLastNotifySwitch = std::nullopt;
265 }
266
chaviwfd6d3512019-03-25 13:23:49 -0700267 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700268 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800269 ASSERT_EQ(touchedToken, mOnPointerDownToken);
270 mOnPointerDownToken.clear();
271 }
272
273 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700274 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800275 ASSERT_TRUE(mOnPointerDownToken == nullptr)
276 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700277 }
278
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700279 // This function must be called soon after the expected ANR timer starts,
280 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500281 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700282 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500283 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800284 std::unique_lock lock(mLock);
285 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500286 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800287 ASSERT_NO_FATAL_FAILURE(
288 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500289 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700290 }
291
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000292 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800293 const sp<WindowInfoHandle>& window) {
294 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
295 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
296 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500297 }
298
Prabir Pradhanedd96402022-02-15 01:46:16 -0800299 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
300 const sp<IBinder>& expectedToken,
301 int32_t expectedPid) {
302 std::unique_lock lock(mLock);
303 android::base::ScopedLockAssertion assumeLocked(mLock);
304 AnrResult result;
305 ASSERT_NO_FATAL_FAILURE(result =
306 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
307 const auto& [token, pid] = result;
308 ASSERT_EQ(expectedToken, token);
309 ASSERT_EQ(expectedPid, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500310 }
311
Prabir Pradhanedd96402022-02-15 01:46:16 -0800312 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000313 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500314 std::unique_lock lock(mLock);
315 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800316 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
317 const auto& [token, _] = result;
318 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000319 }
320
Prabir Pradhanedd96402022-02-15 01:46:16 -0800321 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
322 int32_t expectedPid) {
323 std::unique_lock lock(mLock);
324 android::base::ScopedLockAssertion assumeLocked(mLock);
325 AnrResult result;
326 ASSERT_NO_FATAL_FAILURE(
327 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
328 const auto& [token, pid] = result;
329 ASSERT_EQ(expectedToken, token);
330 ASSERT_EQ(expectedPid, pid);
331 }
332
333 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000334 sp<IBinder> getResponsiveWindowToken() {
335 std::unique_lock lock(mLock);
336 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800337 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
338 const auto& [token, _] = result;
339 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700340 }
341
342 void assertNotifyAnrWasNotCalled() {
343 std::scoped_lock lock(mLock);
344 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800345 ASSERT_TRUE(mAnrWindows.empty());
346 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500347 << "ANR was not called, but please also consume the 'connection is responsive' "
348 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700349 }
350
Garfield Tan1c7bc862020-01-28 13:24:04 -0800351 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
352 mConfig.keyRepeatTimeout = timeout;
353 mConfig.keyRepeatDelay = delay;
354 }
355
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000356 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800357 std::unique_lock lock(mLock);
358 base::ScopedLockAssertion assumeLocked(mLock);
359
360 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
361 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000362 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800363 enabled;
364 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000365 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
366 << ") to be called.";
367 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800368 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000369 auto request = *mPointerCaptureRequest;
370 mPointerCaptureRequest.reset();
371 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800372 }
373
374 void assertSetPointerCaptureNotCalled() {
375 std::unique_lock lock(mLock);
376 base::ScopedLockAssertion assumeLocked(mLock);
377
378 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000379 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800380 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000381 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800382 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000383 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800384 }
385
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700386 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
387 const sp<IBinder>& targetToken) {
388 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800389 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800390 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800391 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800392 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800393 }
394
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800395 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
396 std::unique_lock lock(mLock);
397 base::ScopedLockAssertion assumeLocked(mLock);
398 std::optional<sp<IBinder>> receivedToken =
399 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
400 mNotifyInputChannelBroken);
401 ASSERT_TRUE(receivedToken.has_value());
402 ASSERT_EQ(token, *receivedToken);
403 }
404
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800405 /**
406 * Set policy timeout. A value of zero means next key will not be intercepted.
407 */
408 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
409 mInterceptKeyTimeout = timeout;
410 }
411
Josep del Riob3981622023-04-18 15:49:45 +0000412 void assertUserActivityPoked() {
413 std::scoped_lock lock(mLock);
414 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
415 }
416
417 void assertUserActivityNotPoked() {
418 std::scoped_lock lock(mLock);
419 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
420 }
421
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000422 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<int32_t> uids) {
423 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
424 }
425
426 void assertNotifyDeviceInteractionWasNotCalled() {
427 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
428 }
429
Michael Wrightd02c5b62014-02-10 15:10:22 -0800430private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700431 std::mutex mLock;
432 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
433 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
434 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
435 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800436
Prabir Pradhan99987712020-11-10 18:43:05 -0800437 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000438
439 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800440
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700441 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700442 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800443 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
444 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700445 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800446 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
447 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700448
arthurhungf452d0b2021-01-06 00:19:52 +0800449 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800450 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000451 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800452
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800453 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
454
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000455 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<int32_t /*uid*/>>> mNotifiedInteractions;
456
Prabir Pradhanedd96402022-02-15 01:46:16 -0800457 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
458 // for a specific container to become non-empty. When the container is non-empty, return the
459 // first entry from the container and erase it.
460 template <class T>
461 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
462 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
463 // If there is an ANR, Dispatcher won't be idle because there are still events
464 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
465 // before checking if ANR was called.
466 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
467 // to provide it some time to act. 100ms seems reasonable.
468 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
469 const std::chrono::time_point start = std::chrono::steady_clock::now();
470 std::optional<T> token =
471 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
472 if (!token.has_value()) {
473 ADD_FAILURE() << "Did not receive the ANR callback";
474 return {};
475 }
476
477 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
478 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
479 // the dispatcher started counting before this function was called
480 if (std::chrono::abs(timeout - waited) > 100ms) {
481 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
482 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
483 << "ms, but waited "
484 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
485 << "ms instead";
486 }
487 return *token;
488 }
489
490 template <class T>
491 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
492 std::queue<T>& storage,
493 std::unique_lock<std::mutex>& lock,
494 std::condition_variable& condition)
495 REQUIRES(mLock) {
496 condition.wait_for(lock, timeout,
497 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
498 if (storage.empty()) {
499 ADD_FAILURE() << "Did not receive the expected callback";
500 return std::nullopt;
501 }
502 T item = storage.front();
503 storage.pop();
504 return std::make_optional(item);
505 }
506
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600507 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700508 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800509 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800510 }
511
Prabir Pradhanedd96402022-02-15 01:46:16 -0800512 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
513 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700514 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800515 ASSERT_TRUE(pid.has_value());
516 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700517 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500518 }
519
Prabir Pradhanedd96402022-02-15 01:46:16 -0800520 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
521 std::optional<int32_t> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500522 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800523 ASSERT_TRUE(pid.has_value());
524 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500525 mNotifyAnr.notify_all();
526 }
527
528 void notifyNoFocusedWindowAnr(
529 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
530 std::scoped_lock lock(mLock);
531 mAnrApplications.push(applicationHandle);
532 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800533 }
534
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800535 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
536 std::scoped_lock lock(mLock);
537 mBrokenInputChannels.push(connectionToken);
538 mNotifyInputChannelBroken.notify_all();
539 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800540
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600541 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700542
Chris Yef59a2f42020-10-16 12:55:26 -0700543 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
544 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
545 const std::vector<float>& values) override {}
546
547 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
548 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000549
Chris Yefb552902021-02-03 17:18:37 -0800550 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
551
Prabir Pradhana41d2442023-04-20 21:30:40 +0000552 InputDispatcherConfiguration getDispatcherConfiguration() override { return mConfig; }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800553
Prabir Pradhana41d2442023-04-20 21:30:40 +0000554 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700555 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000556 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700557 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000558 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
559 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800560 break;
561 }
562
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700563 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000564 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
565 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800566 break;
567 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700568 default: {
569 ADD_FAILURE() << "Should only filter keys or motions";
570 break;
571 }
Jackal Guof9696682018-10-05 12:23:23 +0800572 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800573 return true;
574 }
575
Prabir Pradhana41d2442023-04-20 21:30:40 +0000576 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
577 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800578 // Clear intercept state when we handled the event.
579 mInterceptKeyTimeout = 0ms;
580 }
581 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800582
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600583 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800584
Prabir Pradhana41d2442023-04-20 21:30:40 +0000585 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800586 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
587 // Clear intercept state so we could dispatch the event in next wake.
588 mInterceptKeyTimeout = 0ms;
589 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800590 }
591
Prabir Pradhana41d2442023-04-20 21:30:40 +0000592 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
593 uint32_t) override {
594 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800595 }
596
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600597 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
598 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700599 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800600 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
601 * essentially a passthrough for notifySwitch.
602 */
Harry Cutts33476232023-01-30 19:57:29 +0000603 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800604 }
605
Josep del Riob3981622023-04-18 15:49:45 +0000606 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
607 std::scoped_lock lock(mLock);
608 mPokedUserActivity = true;
609 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800610
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600611 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700612 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700613 mOnPointerDownToken = newToken;
614 }
615
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000616 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800617 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000618 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800619 mPointerCaptureChangedCondition.notify_all();
620 }
621
arthurhungf452d0b2021-01-06 00:19:52 +0800622 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
623 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800624 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800625 mDropTargetWindowToken = token;
626 }
627
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000628 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
629 const std::set<int32_t>& uids) override {
630 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
631 }
632
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700633 void assertFilterInputEventWasCalledInternal(
634 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700635 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800636 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700637 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800638 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800639 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800640};
641
Michael Wrightd02c5b62014-02-10 15:10:22 -0800642// --- InputDispatcherTest ---
643
644class InputDispatcherTest : public testing::Test {
645protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000646 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700647 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800648
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000649 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000650 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
651 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800652 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000653 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700654 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800655 }
656
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000657 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700658 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000659 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700660 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800661 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700662
663 /**
664 * Used for debugging when writing the test
665 */
666 void dumpDispatcherState() {
667 std::string dump;
668 mDispatcher->dump(dump);
669 std::stringstream ss(dump);
670 std::string to;
671
672 while (std::getline(ss, to, '\n')) {
673 ALOGE("%s", to.c_str());
674 }
675 }
Vishnu Nair958da932020-08-21 17:12:37 -0700676
Chavi Weingarten847e8512023-03-29 00:26:09 +0000677 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700678 FocusRequest request;
679 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000680 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700681 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
682 request.displayId = window->getInfo()->displayId;
683 mDispatcher->setFocusedWindow(request);
684 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800685};
686
Michael Wrightd02c5b62014-02-10 15:10:22 -0800687TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
688 KeyEvent event;
689
690 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800691 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
692 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600693 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
694 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800695 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000696 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000697 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800698 << "Should reject key events with undefined action.";
699
700 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800701 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
702 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600703 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800704 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000705 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000706 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800707 << "Should reject key events with ACTION_MULTIPLE.";
708}
709
710TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
711 MotionEvent event;
712 PointerProperties pointerProperties[MAX_POINTERS + 1];
713 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800714 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800715 pointerProperties[i].clear();
716 pointerProperties[i].id = i;
717 pointerCoords[i].clear();
718 }
719
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800720 // Some constants commonly used below
721 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
722 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
723 constexpr int32_t metaState = AMETA_NONE;
724 constexpr MotionClassification classification = MotionClassification::NONE;
725
chaviw9eaa22c2020-07-01 16:21:27 -0700726 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800727 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800728 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700729 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
730 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700731 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
732 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700733 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800734 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000735 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000736 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800737 << "Should reject motion events with undefined action.";
738
739 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800740 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800741 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
742 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
743 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
744 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500745 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800746 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000747 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000748 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800749 << "Should reject motion events with pointer down index too large.";
750
Garfield Tanfbe732e2020-01-24 11:26:14 -0800751 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700752 AMOTION_EVENT_ACTION_POINTER_DOWN |
753 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700754 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
755 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700756 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500757 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800758 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000759 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000760 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800761 << "Should reject motion events with pointer down index too small.";
762
763 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800764 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800765 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
766 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
767 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
768 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500769 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800770 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000771 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000772 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800773 << "Should reject motion events with pointer up index too large.";
774
Garfield Tanfbe732e2020-01-24 11:26:14 -0800775 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700776 AMOTION_EVENT_ACTION_POINTER_UP |
777 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700778 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
779 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700780 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500781 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800782 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000783 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000784 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800785 << "Should reject motion events with pointer up index too small.";
786
787 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800788 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
789 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700790 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700791 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
792 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700793 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800794 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000795 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000796 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800797 << "Should reject motion events with 0 pointers.";
798
Garfield Tanfbe732e2020-01-24 11:26:14 -0800799 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
800 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700801 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700802 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
803 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700804 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800805 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000806 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000807 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800808 << "Should reject motion events with more than MAX_POINTERS pointers.";
809
810 // Rejects motion events with invalid pointer ids.
811 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800812 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
813 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700814 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700815 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
816 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700817 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800818 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000819 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000820 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800821 << "Should reject motion events with pointer ids less than 0.";
822
823 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800824 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
825 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700826 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700827 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
828 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700829 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800830 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000831 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000832 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800833 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
834
835 // Rejects motion events with duplicate pointer ids.
836 pointerProperties[0].id = 1;
837 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800838 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
839 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700840 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700841 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
842 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700843 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800844 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000845 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000846 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800847 << "Should reject motion events with duplicate pointer ids.";
848}
849
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800850/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
851
852TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
853 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000854 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800855 ASSERT_TRUE(mDispatcher->waitForIdle());
856
857 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
858}
859
860TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000861 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
862 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000863 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800864
865 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
866 args.policyFlags |= POLICY_FLAG_TRUSTED;
867 mFakePolicy->assertNotifySwitchWasCalled(args);
868}
869
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700870namespace {
871
Arthur Hungb92218b2018-08-14 12:00:21 +0800872// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700873static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700874// Default input dispatching timeout if there is no focused application or paused window
875// from which to determine an appropriate dispatching timeout.
876static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
877 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
878 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800879
880class FakeApplicationHandle : public InputApplicationHandle {
881public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700882 FakeApplicationHandle() {
883 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700884 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500885 mInfo.dispatchingTimeoutMillis =
886 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700887 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800888 virtual ~FakeApplicationHandle() {}
889
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000890 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700891
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500892 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
893 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700894 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800895};
896
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800897class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800898public:
Garfield Tan15601662020-09-22 15:32:38 -0700899 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800900 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700901 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800902 }
903
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800904 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700905 InputEvent* event;
906 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
907 if (!consumeSeq) {
908 return nullptr;
909 }
910 finishEvent(*consumeSeq);
911 return event;
912 }
913
914 /**
915 * Receive an event without acknowledging it.
916 * Return the sequence number that could later be used to send finished signal.
917 */
918 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800919 uint32_t consumeSeq;
920 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800921
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800922 std::chrono::time_point start = std::chrono::steady_clock::now();
923 status_t status = WOULD_BLOCK;
924 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000925 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800926 &event);
927 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
928 if (elapsed > 100ms) {
929 break;
930 }
931 }
932
933 if (status == WOULD_BLOCK) {
934 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700935 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800936 }
937
938 if (status != OK) {
939 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700940 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800941 }
942 if (event == nullptr) {
943 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700944 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800945 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700946 if (outEvent != nullptr) {
947 *outEvent = event;
948 }
949 return consumeSeq;
950 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800951
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700952 /**
953 * To be used together with "receiveEvent" to complete the consumption of an event.
954 */
955 void finishEvent(uint32_t consumeSeq) {
956 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
957 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800958 }
959
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000960 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
961 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
962 ASSERT_EQ(OK, status);
963 }
964
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700965 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000966 std::optional<int32_t> expectedDisplayId,
967 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800968 InputEvent* event = consume();
969
970 ASSERT_NE(nullptr, event) << mName.c_str()
971 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800972 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700973 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
974 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800975
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000976 if (expectedDisplayId.has_value()) {
977 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
978 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800979
Tiger Huang8664f8c2018-10-11 19:14:35 +0800980 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700981 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800982 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
983 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000984 if (expectedFlags.has_value()) {
985 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
986 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800987 break;
988 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700989 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800990 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000991 assertMotionAction(expectedAction, motionEvent.getAction());
992
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000993 if (expectedFlags.has_value()) {
994 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
995 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800996 break;
997 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700998 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100999 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
1000 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001001 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -08001002 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
1003 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001004 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001005 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
1006 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001007 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001008 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1009 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001010 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001011 }
1012
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001013 MotionEvent* consumeMotion() {
1014 InputEvent* event = consume();
1015
1016 if (event == nullptr) {
1017 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1018 return nullptr;
1019 }
1020
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001021 if (event->getType() != InputEventType::MOTION) {
1022 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001023 return nullptr;
1024 }
1025 return static_cast<MotionEvent*>(event);
1026 }
1027
1028 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1029 MotionEvent* motionEvent = consumeMotion();
1030 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1031 ASSERT_THAT(*motionEvent, matcher);
1032 }
1033
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001034 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1035 InputEvent* event = consume();
1036 ASSERT_NE(nullptr, event) << mName.c_str()
1037 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001038 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1039 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001040
1041 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1042 << mName.c_str() << ": event displayId should always be NONE.";
1043
1044 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1045 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001046 }
1047
Prabir Pradhan99987712020-11-10 18:43:05 -08001048 void consumeCaptureEvent(bool hasCapture) {
1049 const InputEvent* event = consume();
1050 ASSERT_NE(nullptr, event) << mName.c_str()
1051 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001052 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1053 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001054
1055 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1056 << mName.c_str() << ": event displayId should always be NONE.";
1057
1058 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1059 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1060 }
1061
arthurhungb89ccb02020-12-30 16:19:01 +08001062 void consumeDragEvent(bool isExiting, float x, float y) {
1063 const InputEvent* event = consume();
1064 ASSERT_NE(nullptr, event) << mName.c_str()
1065 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001066 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001067
1068 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1069 << mName.c_str() << ": event displayId should always be NONE.";
1070
1071 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1072 EXPECT_EQ(isExiting, dragEvent.isExiting());
1073 EXPECT_EQ(x, dragEvent.getX());
1074 EXPECT_EQ(y, dragEvent.getY());
1075 }
1076
Antonio Kantekf16f2832021-09-28 04:39:20 +00001077 void consumeTouchModeEvent(bool inTouchMode) {
1078 const InputEvent* event = consume();
1079 ASSERT_NE(nullptr, event) << mName.c_str()
1080 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001081 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1082 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001083
1084 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1085 << mName.c_str() << ": event displayId should always be NONE.";
1086 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1087 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1088 }
1089
chaviwd1c23182019-12-20 18:44:56 -08001090 void assertNoEvents() {
1091 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001092 if (event == nullptr) {
1093 return;
1094 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001095 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001096 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1097 ADD_FAILURE() << "Received key event "
1098 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001099 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001100 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1101 ADD_FAILURE() << "Received motion event "
1102 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001103 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001104 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1105 ADD_FAILURE() << "Received focus event, hasFocus = "
1106 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001107 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001108 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1109 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1110 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001111 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001112 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1113 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1114 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001115 }
1116 FAIL() << mName.c_str()
1117 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001118 }
1119
1120 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1121
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001122 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1123
chaviwd1c23182019-12-20 18:44:56 -08001124protected:
1125 std::unique_ptr<InputConsumer> mConsumer;
1126 PreallocatedInputEventFactory mEventFactory;
1127
1128 std::string mName;
1129};
1130
chaviw3277faf2021-05-19 16:45:23 -05001131class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001132public:
1133 static const int32_t WIDTH = 600;
1134 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001135
Chris Yea209fde2020-07-22 13:54:51 -07001136 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001137 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001138 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001139 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001140 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001141 base::Result<std::unique_ptr<InputChannel>> channel =
1142 dispatcher->createInputChannel(name);
1143 token = (*channel)->getConnectionToken();
1144 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001145 }
1146
1147 inputApplicationHandle->updateInfo();
1148 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1149
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001150 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001151 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001152 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001153 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001154 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001155 mInfo.frameLeft = 0;
1156 mInfo.frameTop = 0;
1157 mInfo.frameRight = WIDTH;
1158 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001159 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001160 mInfo.globalScaleFactor = 1.0;
1161 mInfo.touchableRegion.clear();
1162 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001163 mInfo.ownerPid = WINDOW_PID;
1164 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001165 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001166 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001167 }
1168
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001169 sp<FakeWindowHandle> clone(int32_t displayId) {
1170 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1171 handle->mInfo = mInfo;
1172 handle->mInfo.displayId = displayId;
1173 handle->mInfo.id = sId++;
1174 handle->mInputReceiver = mInputReceiver;
1175 return handle;
1176 }
1177
1178 /**
1179 * This is different from clone, because clone will make a "mirror" window - a window with the
1180 * same token, but a different ID. The original window and the clone window are allowed to be
1181 * sent to the dispatcher at the same time - they can coexist inside the dispatcher.
1182 * This function will create a different object of WindowInfoHandle, but with the same
1183 * properties as the original object - including the ID.
1184 * You can use either the old or the new object to consume the events.
1185 * IMPORTANT: The duplicated object is supposed to replace the original object, and not appear
1186 * at the same time inside dispatcher.
1187 */
1188 sp<FakeWindowHandle> duplicate() {
1189 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mName);
1190 handle->mInfo = mInfo;
1191 handle->mInputReceiver = mInputReceiver;
Arthur Hungabbb9d82021-09-01 14:52:30 +00001192 return handle;
1193 }
1194
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001195 void setTouchable(bool touchable) {
1196 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1197 }
chaviwd1c23182019-12-20 18:44:56 -08001198
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001199 void setFocusable(bool focusable) {
1200 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1201 }
1202
1203 void setVisible(bool visible) {
1204 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1205 }
Vishnu Nair958da932020-08-21 17:12:37 -07001206
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001207 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001208 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001209 }
1210
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001211 void setPaused(bool paused) {
1212 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1213 }
1214
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001215 void setPreventSplitting(bool preventSplitting) {
1216 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001217 }
1218
1219 void setSlippery(bool slippery) {
1220 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1221 }
1222
1223 void setWatchOutsideTouch(bool watchOutside) {
1224 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1225 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001226
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001227 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1228
1229 void setInterceptsStylus(bool interceptsStylus) {
1230 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1231 }
1232
1233 void setDropInput(bool dropInput) {
1234 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1235 }
1236
1237 void setDropInputIfObscured(bool dropInputIfObscured) {
1238 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1239 }
1240
1241 void setNoInputChannel(bool noInputChannel) {
1242 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1243 }
1244
Josep del Riob3981622023-04-18 15:49:45 +00001245 void setDisableUserActivity(bool disableUserActivity) {
1246 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1247 }
1248
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001249 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1250
chaviw3277faf2021-05-19 16:45:23 -05001251 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001252
Bernardo Rufino7393d172021-02-26 13:56:11 +00001253 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1254
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001255 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001256 mInfo.frameLeft = frame.left;
1257 mInfo.frameTop = frame.top;
1258 mInfo.frameRight = frame.right;
1259 mInfo.frameBottom = frame.bottom;
1260 mInfo.touchableRegion.clear();
1261 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001262
1263 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1264 ui::Transform translate;
1265 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1266 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001267 }
1268
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001269 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1270
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001271 void setIsWallpaper(bool isWallpaper) {
1272 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1273 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001274
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001275 void setDupTouchToWallpaper(bool hasWallpaper) {
1276 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1277 }
chaviwd1c23182019-12-20 18:44:56 -08001278
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001279 void setTrustedOverlay(bool trustedOverlay) {
1280 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1281 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001282
chaviw9eaa22c2020-07-01 16:21:27 -07001283 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1284 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1285 }
1286
1287 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001288
yunho.shinf4a80b82020-11-16 21:13:57 +09001289 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1290
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001291 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001292 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001293 }
1294
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001295 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001296 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001297 }
1298
Svet Ganov5d3bc372020-01-26 23:11:07 -08001299 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001300 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001301 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1302 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001303 }
1304
1305 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001306 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001307 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1308 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001309 }
1310
1311 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001312 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001313 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1314 }
1315
1316 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1317 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001318 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001319 expectedFlags);
1320 }
1321
Svet Ganov5d3bc372020-01-26 23:11:07 -08001322 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001323 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1324 int32_t expectedFlags = 0) {
1325 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1326 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001327 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001328 }
1329
1330 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001331 int32_t expectedFlags = 0) {
1332 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1333 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001334 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001335 }
1336
1337 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001338 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001339 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001340 expectedFlags);
1341 }
1342
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001343 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1344 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001345 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001346 expectedFlags);
1347 }
1348
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001349 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1350 int32_t expectedFlags = 0) {
1351 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001352 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001353 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001354 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1355 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1356 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1357 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1358 }
1359
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001360 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1361 ASSERT_NE(mInputReceiver, nullptr)
1362 << "Cannot consume events from a window with no receiver";
1363 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1364 }
1365
Prabir Pradhan99987712020-11-10 18:43:05 -08001366 void consumeCaptureEvent(bool hasCapture) {
1367 ASSERT_NE(mInputReceiver, nullptr)
1368 << "Cannot consume events from a window with no receiver";
1369 mInputReceiver->consumeCaptureEvent(hasCapture);
1370 }
1371
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001372 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1373 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001374 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001375 ASSERT_THAT(*motionEvent, matcher);
1376 }
1377
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001378 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001379 std::optional<int32_t> expectedDisplayId,
1380 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001381 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1382 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1383 expectedFlags);
1384 }
1385
arthurhungb89ccb02020-12-30 16:19:01 +08001386 void consumeDragEvent(bool isExiting, float x, float y) {
1387 mInputReceiver->consumeDragEvent(isExiting, x, y);
1388 }
1389
Antonio Kantekf16f2832021-09-28 04:39:20 +00001390 void consumeTouchModeEvent(bool inTouchMode) {
1391 ASSERT_NE(mInputReceiver, nullptr)
1392 << "Cannot consume events from a window with no receiver";
1393 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1394 }
1395
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001396 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001397 if (mInputReceiver == nullptr) {
1398 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1399 return std::nullopt;
1400 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001401 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001402 }
1403
1404 void finishEvent(uint32_t sequenceNum) {
1405 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1406 mInputReceiver->finishEvent(sequenceNum);
1407 }
1408
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001409 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1410 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1411 mInputReceiver->sendTimeline(inputEventId, timeline);
1412 }
1413
chaviwaf87b3e2019-10-01 16:59:28 -07001414 InputEvent* consume() {
1415 if (mInputReceiver == nullptr) {
1416 return nullptr;
1417 }
1418 return mInputReceiver->consume();
1419 }
1420
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001421 MotionEvent* consumeMotion() {
1422 InputEvent* event = consume();
1423 if (event == nullptr) {
1424 ADD_FAILURE() << "Consume failed : no event";
1425 return nullptr;
1426 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001427 if (event->getType() != InputEventType::MOTION) {
1428 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001429 return nullptr;
1430 }
1431 return static_cast<MotionEvent*>(event);
1432 }
1433
Arthur Hungb92218b2018-08-14 12:00:21 +08001434 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001435 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001436 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001437 return; // Can't receive events if the window does not have input channel
1438 }
1439 ASSERT_NE(nullptr, mInputReceiver)
1440 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001441 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001442 }
1443
chaviwaf87b3e2019-10-01 16:59:28 -07001444 sp<IBinder> getToken() { return mInfo.token; }
1445
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001446 const std::string& getName() { return mName; }
1447
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001448 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1449 mInfo.ownerPid = ownerPid;
1450 mInfo.ownerUid = ownerUid;
1451 }
1452
Prabir Pradhanedd96402022-02-15 01:46:16 -08001453 int32_t getPid() const { return mInfo.ownerPid; }
1454
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001455 void destroyReceiver() { mInputReceiver = nullptr; }
1456
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001457 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1458
chaviwd1c23182019-12-20 18:44:56 -08001459private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001460 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001461 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001462 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001463 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001464 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001465};
1466
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001467std::atomic<int32_t> FakeWindowHandle::sId{1};
1468
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001469static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001470 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001471 int32_t displayId = ADISPLAY_ID_NONE,
1472 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001473 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001474 bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
1475 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001476 KeyEvent event;
1477 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1478
1479 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001480 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001481 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1482 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001483
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001484 if (!allowKeyRepeat) {
1485 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1486 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001487 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001488 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001489}
1490
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001491static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001492 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001493 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001494}
1495
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001496// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1497// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1498// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001499static InputEventInjectionResult injectKeyDownNoRepeat(
1500 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001501 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001502 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001503 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001504}
1505
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001506static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001507 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001508 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001509}
1510
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001511static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001512 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001513 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001514 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1515 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
1516 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1517 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001518}
1519
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001520static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001521 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001522 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001523 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001524 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1525 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001526 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001527 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
1528 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001529 MotionEventBuilder motionBuilder =
1530 MotionEventBuilder(action, source)
1531 .displayId(displayId)
1532 .eventTime(eventTime)
1533 .rawXCursorPosition(cursorPosition.x)
1534 .rawYCursorPosition(cursorPosition.y)
1535 .pointer(
1536 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1537 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1538 motionBuilder.downTime(eventTime);
1539 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001540
1541 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001542 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1543 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001544}
1545
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001546static InputEventInjectionResult injectMotionDown(
1547 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1548 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001549 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001550}
1551
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001552static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001553 int32_t source, int32_t displayId,
1554 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001555 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001556}
1557
Jackal Guof9696682018-10-05 12:23:23 +08001558static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1559 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1560 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001561 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001562 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1563 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001564
1565 return args;
1566}
1567
Josep del Riob3981622023-04-18 15:49:45 +00001568static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1569 int32_t displayId = ADISPLAY_ID_NONE) {
1570 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1571 // Define a valid key event.
1572 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1573 displayId, 0, action, /* flags */ 0, AKEYCODE_C, KEY_C, AMETA_META_ON,
1574 currentTime);
1575
1576 return args;
1577}
1578
1579static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1580 int32_t displayId = ADISPLAY_ID_NONE) {
1581 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1582 // Define a valid key event.
1583 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1584 displayId, 0, action, /* flags */ 0, AKEYCODE_ASSIST, KEY_ASSISTANT,
1585 AMETA_NONE, currentTime);
1586
1587 return args;
1588}
1589
Prabir Pradhan678438e2023-04-13 19:32:51 +00001590[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1591 int32_t displayId,
1592 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001593 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001594 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1595 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1596 }
1597
chaviwd1c23182019-12-20 18:44:56 -08001598 PointerProperties pointerProperties[pointerCount];
1599 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001600
chaviwd1c23182019-12-20 18:44:56 -08001601 for (size_t i = 0; i < pointerCount; i++) {
1602 pointerProperties[i].clear();
1603 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001604 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001605
chaviwd1c23182019-12-20 18:44:56 -08001606 pointerCoords[i].clear();
1607 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1608 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1609 }
Jackal Guof9696682018-10-05 12:23:23 +08001610
1611 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1612 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001613 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001614 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1615 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001616 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1617 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001618 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1619 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001620
1621 return args;
1622}
1623
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001624static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1625 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1626}
1627
chaviwd1c23182019-12-20 18:44:56 -08001628static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1629 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1630}
1631
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001632static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1633 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001634 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001635}
1636
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001637} // namespace
1638
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001639/**
1640 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1641 * broken channel.
1642 */
1643TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1644 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1645 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001646 sp<FakeWindowHandle>::make(application, mDispatcher,
1647 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001648
1649 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1650
1651 // Window closes its channel, but the window remains.
1652 window->destroyReceiver();
1653 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1654}
1655
Arthur Hungb92218b2018-08-14 12:00:21 +08001656TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001657 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001658 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1659 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001660
Arthur Hung72d8dc32020-03-28 00:48:39 +00001661 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001662 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1663 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1664 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001665
1666 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001667 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001668}
1669
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001670TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1671 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001672 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1673 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001674
1675 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1676 // Inject a MotionEvent to an unknown display.
1677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1678 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1679 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1680
1681 // Window should receive motion event.
1682 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1683}
1684
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001685/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001686 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001687 * This test serves as a sanity check for the next test, where setInputWindows is
1688 * called twice.
1689 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001690TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001691 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001692 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1693 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001694 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001695
1696 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001698 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1699 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001700 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001701
1702 // Window should receive motion event.
1703 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1704}
1705
1706/**
1707 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001708 */
1709TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001711 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1712 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001713 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001714
1715 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1716 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001718 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1719 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001720 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001721
1722 // Window should receive motion event.
1723 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1724}
1725
Arthur Hungb92218b2018-08-14 12:00:21 +08001726// The foreground window should receive the first touch down event.
1727TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001728 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001729 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001730 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001731 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001732 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001733
Arthur Hung72d8dc32020-03-28 00:48:39 +00001734 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001735 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1736 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1737 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001738
1739 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001740 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001741 windowSecond->assertNoEvents();
1742}
1743
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001744/**
1745 * Two windows: A top window, and a wallpaper behind the window.
1746 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1747 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001748 * 1. foregroundWindow <-- dup touch to wallpaper
1749 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001750 */
1751TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1752 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1753 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001754 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001755 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001756 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001757 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001758 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001759
1760 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1762 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1763 {100, 200}))
1764 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1765
1766 // Both foreground window and its wallpaper should receive the touch down
1767 foregroundWindow->consumeMotionDown();
1768 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1769
1770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1771 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1772 ADISPLAY_ID_DEFAULT, {110, 200}))
1773 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1774
1775 foregroundWindow->consumeMotionMove();
1776 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1777
1778 // Now the foreground window goes away, but the wallpaper stays
1779 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1780 foregroundWindow->consumeMotionCancel();
1781 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1782 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1783}
1784
1785/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001786 * Two fingers down on the window, and lift off the first finger.
1787 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1788 * contains a single pointer.
1789 */
1790TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1791 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1792 sp<FakeWindowHandle> window =
1793 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1794
1795 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001796 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001797 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1798 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1799 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001800 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001801 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1802 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1803 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1804 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001805 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001806 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1807 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1808 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1809 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001810 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1811 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1812 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1813
1814 // Remove the window. The gesture should be canceled
1815 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
1816 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1817 window->consumeMotionEvent(
1818 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1819}
1820
1821/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001822 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1823 * with the following differences:
1824 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1825 * clean up the connection.
1826 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1827 * Ensure that there's no crash in the dispatcher.
1828 */
1829TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1830 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1831 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001832 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001833 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001834 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001835 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001836 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001837
1838 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1840 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1841 {100, 200}))
1842 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1843
1844 // Both foreground window and its wallpaper should receive the touch down
1845 foregroundWindow->consumeMotionDown();
1846 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1847
1848 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1849 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1850 ADISPLAY_ID_DEFAULT, {110, 200}))
1851 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1852
1853 foregroundWindow->consumeMotionMove();
1854 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1855
1856 // Wallpaper closes its channel, but the window remains.
1857 wallpaperWindow->destroyReceiver();
1858 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1859
1860 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1861 // is no longer valid.
1862 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1863 foregroundWindow->consumeMotionCancel();
1864}
1865
Arthur Hungc539dbb2022-12-08 07:45:36 +00001866class ShouldSplitTouchFixture : public InputDispatcherTest,
1867 public ::testing::WithParamInterface<bool> {};
1868INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1869 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001870/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001871 * A single window that receives touch (on top), and a wallpaper window underneath it.
1872 * The top window gets a multitouch gesture.
1873 * Ensure that wallpaper gets the same gesture.
1874 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001875TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001876 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001877 sp<FakeWindowHandle> foregroundWindow =
1878 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1879 foregroundWindow->setDupTouchToWallpaper(true);
1880 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001881
1882 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001883 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001884 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001885
Arthur Hungc539dbb2022-12-08 07:45:36 +00001886 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001887
1888 // Touch down on top window
1889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1890 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1891 {100, 100}))
1892 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1893
1894 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001895 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001896 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1897
1898 // Second finger down on the top window
1899 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001900 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001901 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001902 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1903 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001904 .build();
1905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1906 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1907 InputEventInjectionSync::WAIT_FOR_RESULT))
1908 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1909
Harry Cutts33476232023-01-30 19:57:29 +00001910 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1911 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001912 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001913
1914 const MotionEvent secondFingerUpEvent =
1915 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1916 .displayId(ADISPLAY_ID_DEFAULT)
1917 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001918 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1919 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001920 .build();
1921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1922 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
1923 InputEventInjectionSync::WAIT_FOR_RESULT))
1924 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1925 foregroundWindow->consumeMotionPointerUp(0);
1926 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1927
1928 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001929 injectMotionEvent(mDispatcher,
1930 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1931 AINPUT_SOURCE_TOUCHSCREEN)
1932 .displayId(ADISPLAY_ID_DEFAULT)
1933 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1934 .pointer(PointerBuilder(/* id */ 1,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001935 ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001936 .x(100)
1937 .y(100))
1938 .build(),
1939 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001940 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1941 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1942 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001943}
1944
1945/**
1946 * Two windows: a window on the left and window on the right.
1947 * A third window, wallpaper, is behind both windows, and spans both top windows.
1948 * The first touch down goes to the left window. A second pointer touches down on the right window.
1949 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1950 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1951 * ACTION_POINTER_DOWN(1).
1952 */
1953TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1954 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1955 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001956 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001957 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001958 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001959
1960 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001961 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001962 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001963 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001964
1965 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001966 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001967 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001968 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001969
1970 mDispatcher->setInputWindows(
1971 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1972
1973 // Touch down on left window
1974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1975 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1976 {100, 100}))
1977 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1978
1979 // Both foreground window and its wallpaper should receive the touch down
1980 leftWindow->consumeMotionDown();
1981 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1982
1983 // Second finger down on the right window
1984 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001985 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001986 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001987 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1988 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001989 .build();
1990 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1991 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1992 InputEventInjectionSync::WAIT_FOR_RESULT))
1993 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1994
1995 leftWindow->consumeMotionMove();
1996 // Since the touch is split, right window gets ACTION_DOWN
1997 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001998 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001999 expectedWallpaperFlags);
2000
2001 // Now, leftWindow, which received the first finger, disappears.
2002 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
2003 leftWindow->consumeMotionCancel();
2004 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2005 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2006
2007 // The pointer that's still down on the right window moves, and goes to the right window only.
2008 // As far as the dispatcher's concerned though, both pointers are still present.
2009 const MotionEvent secondFingerMoveEvent =
2010 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2011 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002012 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2013 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002014 .build();
2015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2016 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2017 InputEventInjectionSync::WAIT_FOR_RESULT));
2018 rightWindow->consumeMotionMove();
2019
2020 leftWindow->assertNoEvents();
2021 rightWindow->assertNoEvents();
2022 wallpaperWindow->assertNoEvents();
2023}
2024
Arthur Hungc539dbb2022-12-08 07:45:36 +00002025/**
2026 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2027 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2028 * The right window should receive ACTION_DOWN.
2029 */
2030TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002031 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002032 sp<FakeWindowHandle> leftWindow =
2033 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2034 leftWindow->setFrame(Rect(0, 0, 200, 200));
2035 leftWindow->setDupTouchToWallpaper(true);
2036 leftWindow->setSlippery(true);
2037
2038 sp<FakeWindowHandle> rightWindow =
2039 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2040 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002041
2042 sp<FakeWindowHandle> wallpaperWindow =
2043 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2044 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002045
Arthur Hungc539dbb2022-12-08 07:45:36 +00002046 mDispatcher->setInputWindows(
2047 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002048
Arthur Hungc539dbb2022-12-08 07:45:36 +00002049 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2051 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002052 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002053 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002054
2055 // Both foreground window and its wallpaper should receive the touch down
2056 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002057 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2058
Arthur Hungc539dbb2022-12-08 07:45:36 +00002059 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002061 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2062 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002063 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2064
Arthur Hungc539dbb2022-12-08 07:45:36 +00002065 leftWindow->consumeMotionCancel();
2066 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2067 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002068}
2069
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002070/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002071 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2072 * interactive, it might stop sending this flag.
2073 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2074 * to have a consistent input stream.
2075 *
2076 * Test procedure:
2077 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2078 * DOWN (new gesture).
2079 *
2080 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2081 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2082 *
2083 * We technically just need a single window here, but we are using two windows (spy on top and a
2084 * regular window below) to emulate the actual situation where it happens on the device.
2085 */
2086TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2087 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2088 sp<FakeWindowHandle> spyWindow =
2089 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2090 spyWindow->setFrame(Rect(0, 0, 200, 200));
2091 spyWindow->setTrustedOverlay(true);
2092 spyWindow->setSpy(true);
2093
2094 sp<FakeWindowHandle> window =
2095 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2096 window->setFrame(Rect(0, 0, 200, 200));
2097
2098 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2099 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002100
2101 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002102 mDispatcher->notifyMotion(
2103 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2104 .deviceId(touchDeviceId)
2105 .policyFlags(DEFAULT_POLICY_FLAGS)
2106 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2107 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002108
Prabir Pradhan678438e2023-04-13 19:32:51 +00002109 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2110 .deviceId(touchDeviceId)
2111 .policyFlags(DEFAULT_POLICY_FLAGS)
2112 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2113 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2114 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002115 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2116 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2117 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2118 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2119
2120 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002121 mDispatcher->notifyMotion(
2122 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2123 .deviceId(touchDeviceId)
2124 .policyFlags(0)
2125 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2126 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2127 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002128 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2129 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2130
2131 // We don't need to reset the device to reproduce the issue, but the reset event typically
2132 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002133 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002134
2135 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002136 mDispatcher->notifyMotion(
2137 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2138 .deviceId(touchDeviceId)
2139 .policyFlags(DEFAULT_POLICY_FLAGS)
2140 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2141 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002142 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2143 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2144
2145 // No more events
2146 spyWindow->assertNoEvents();
2147 window->assertNoEvents();
2148}
2149
2150/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002151 * Two windows: a window on the left and a window on the right.
2152 * Mouse is hovered from the right window into the left window.
2153 * Next, we tap on the left window, where the cursor was last seen.
2154 * The second tap is done onto the right window.
2155 * The mouse and tap are from two different devices.
2156 * We technically don't need to set the downtime / eventtime for these events, but setting these
2157 * explicitly helps during debugging.
2158 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2159 * In the buggy implementation, a tap on the right window would cause a crash.
2160 */
2161TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2162 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2163 sp<FakeWindowHandle> leftWindow =
2164 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2165 leftWindow->setFrame(Rect(0, 0, 200, 200));
2166
2167 sp<FakeWindowHandle> rightWindow =
2168 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2169 rightWindow->setFrame(Rect(200, 0, 400, 200));
2170
2171 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2172 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2173 // stale.
2174 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2175 const int32_t mouseDeviceId = 6;
2176 const int32_t touchDeviceId = 4;
2177 // Move the cursor from right
2178 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2179 injectMotionEvent(mDispatcher,
2180 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2181 AINPUT_SOURCE_MOUSE)
2182 .deviceId(mouseDeviceId)
2183 .downTime(baseTime + 10)
2184 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002185 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002186 .x(300)
2187 .y(100))
2188 .build()));
2189 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2190
2191 // .. to the left window
2192 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2193 injectMotionEvent(mDispatcher,
2194 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2195 AINPUT_SOURCE_MOUSE)
2196 .deviceId(mouseDeviceId)
2197 .downTime(baseTime + 10)
2198 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002199 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002200 .x(110)
2201 .y(100))
2202 .build()));
2203 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2204 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2205 // Now tap the left window
2206 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2207 injectMotionEvent(mDispatcher,
2208 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2209 AINPUT_SOURCE_TOUCHSCREEN)
2210 .deviceId(touchDeviceId)
2211 .downTime(baseTime + 40)
2212 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002213 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002214 .x(100)
2215 .y(100))
2216 .build()));
2217 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2218 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2219
2220 // release tap
2221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2222 injectMotionEvent(mDispatcher,
2223 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2224 AINPUT_SOURCE_TOUCHSCREEN)
2225 .deviceId(touchDeviceId)
2226 .downTime(baseTime + 40)
2227 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002228 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002229 .x(100)
2230 .y(100))
2231 .build()));
2232 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2233
2234 // Tap the window on the right
2235 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2236 injectMotionEvent(mDispatcher,
2237 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2238 AINPUT_SOURCE_TOUCHSCREEN)
2239 .deviceId(touchDeviceId)
2240 .downTime(baseTime + 60)
2241 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002242 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002243 .x(300)
2244 .y(100))
2245 .build()));
2246 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2247
2248 // release tap
2249 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2250 injectMotionEvent(mDispatcher,
2251 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2252 AINPUT_SOURCE_TOUCHSCREEN)
2253 .deviceId(touchDeviceId)
2254 .downTime(baseTime + 60)
2255 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002256 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002257 .x(300)
2258 .y(100))
2259 .build()));
2260 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2261
2262 // No more events
2263 leftWindow->assertNoEvents();
2264 rightWindow->assertNoEvents();
2265}
2266
2267/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002268 * Start hovering in a window. While this hover is still active, make another window appear on top.
2269 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2270 * While the top window is present, the hovering is stopped.
2271 * Later, hovering gets resumed again.
2272 * Ensure that new hover gesture is handled correctly.
2273 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2274 * to the window that's currently being hovered over.
2275 */
2276TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2277 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2278 sp<FakeWindowHandle> window =
2279 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2280 window->setFrame(Rect(0, 0, 200, 200));
2281
2282 // Only a single window is present at first
2283 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2284
2285 // Start hovering in the window
2286 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2287 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2288 .build());
2289 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2290
2291 // Now, an obscuring window appears!
2292 sp<FakeWindowHandle> obscuringWindow =
2293 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2294 ADISPLAY_ID_DEFAULT,
2295 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2296 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2297 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2298 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2299 obscuringWindow->setNoInputChannel(true);
2300 obscuringWindow->setFocusable(false);
2301 obscuringWindow->setAlpha(1.0);
2302 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2303
2304 // While this new obscuring window is present, the hovering is stopped
2305 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2306 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2307 .build());
2308 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2309
2310 // Now the obscuring window goes away.
2311 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2312
2313 // And a new hover gesture starts.
2314 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2315 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2316 .build());
2317 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2318}
2319
2320/**
2321 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2322 * the obscuring window.
2323 */
2324TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2325 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2326 sp<FakeWindowHandle> window =
2327 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2328 window->setFrame(Rect(0, 0, 200, 200));
2329
2330 // Only a single window is present at first
2331 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2332
2333 // Start hovering in the window
2334 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2335 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2336 .build());
2337 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2338
2339 // Now, an obscuring window appears!
2340 sp<FakeWindowHandle> obscuringWindow =
2341 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2342 ADISPLAY_ID_DEFAULT,
2343 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2344 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2345 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2346 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2347 obscuringWindow->setNoInputChannel(true);
2348 obscuringWindow->setFocusable(false);
2349 obscuringWindow->setAlpha(1.0);
2350 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2351
2352 // While this new obscuring window is present, the hovering continues. The event can't go to the
2353 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2354 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2355 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2356 .build());
2357 obscuringWindow->assertNoEvents();
2358 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2359
2360 // Now the obscuring window goes away.
2361 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2362
2363 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2364 // so it should generate a HOVER_ENTER
2365 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2366 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2367 .build());
2368 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2369
2370 // Now the MOVE should be getting dispatched normally
2371 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2372 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2373 .build());
2374 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2375}
2376
2377/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002378 * Two windows: a window on the left and a window on the right.
2379 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2380 * down. Then, on the left window, also place second touch pointer down.
2381 * This test tries to reproduce a crash.
2382 * In the buggy implementation, second pointer down on the left window would cause a crash.
2383 */
2384TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2385 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2386 sp<FakeWindowHandle> leftWindow =
2387 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2388 leftWindow->setFrame(Rect(0, 0, 200, 200));
2389
2390 sp<FakeWindowHandle> rightWindow =
2391 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2392 rightWindow->setFrame(Rect(200, 0, 400, 200));
2393
2394 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2395
2396 const int32_t touchDeviceId = 4;
2397 const int32_t mouseDeviceId = 6;
2398 NotifyMotionArgs args;
2399
2400 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002401 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2402 .deviceId(mouseDeviceId)
2403 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2404 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002405 leftWindow->consumeMotionEvent(
2406 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2407
2408 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002409 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2410 .deviceId(mouseDeviceId)
2411 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2412 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2413 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002414
2415 leftWindow->consumeMotionEvent(
2416 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2417 leftWindow->consumeMotionEvent(
2418 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2419
Prabir Pradhan678438e2023-04-13 19:32:51 +00002420 mDispatcher->notifyMotion(
2421 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2422 .deviceId(mouseDeviceId)
2423 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2424 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2425 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2426 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002427 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2428
2429 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002430 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2431 .deviceId(touchDeviceId)
2432 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2433 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002434 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2435
2436 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2437
2438 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002439 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2440 .deviceId(touchDeviceId)
2441 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2442 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2443 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002444 leftWindow->consumeMotionEvent(
2445 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2446 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2447 // current implementation.
2448 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2449 rightWindow->consumeMotionEvent(
2450 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2451
2452 leftWindow->assertNoEvents();
2453 rightWindow->assertNoEvents();
2454}
2455
2456/**
2457 * On a single window, use two different devices: mouse and touch.
2458 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2459 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2460 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2461 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2462 * represent a new gesture.
2463 */
2464TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2465 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2466 sp<FakeWindowHandle> window =
2467 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2468 window->setFrame(Rect(0, 0, 400, 400));
2469
2470 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2471
2472 const int32_t touchDeviceId = 4;
2473 const int32_t mouseDeviceId = 6;
2474 NotifyMotionArgs args;
2475
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002476 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002477 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2478 .deviceId(touchDeviceId)
2479 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2480 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002481 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002482 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2483 .deviceId(touchDeviceId)
2484 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2485 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2486 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002487 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002488 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2489 .deviceId(touchDeviceId)
2490 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2491 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2492 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002493 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2494 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2495 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2496
2497 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002498 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2499 .deviceId(mouseDeviceId)
2500 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2501 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2502 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002503
2504 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002505 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002506 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2507
Prabir Pradhan678438e2023-04-13 19:32:51 +00002508 mDispatcher->notifyMotion(
2509 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2510 .deviceId(mouseDeviceId)
2511 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2512 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2513 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2514 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002515 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2516
2517 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002518 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2519 .deviceId(touchDeviceId)
2520 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2521 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2522 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002523 // The pointer_down event should be ignored
2524 window->assertNoEvents();
2525}
2526
2527/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002528 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2529 * the injected event.
2530 */
2531TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2532 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2533 sp<FakeWindowHandle> window =
2534 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2535 window->setFrame(Rect(0, 0, 400, 400));
2536
2537 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2538
2539 const int32_t touchDeviceId = 4;
2540 NotifyMotionArgs args;
2541 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2542 // completion.
2543 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2544 injectMotionEvent(mDispatcher,
2545 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2546 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002547 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002548 .x(50)
2549 .y(50))
2550 .build()));
2551 window->consumeMotionEvent(
2552 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2553
2554 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2555 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002556 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2557 .deviceId(touchDeviceId)
2558 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2559 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002560
2561 window->consumeMotionEvent(
2562 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2563 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2564}
2565
2566/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002567 * This test is similar to the test above, but the sequence of injected events is different.
2568 *
2569 * Two windows: a window on the left and a window on the right.
2570 * Mouse is hovered over the left window.
2571 * Next, we tap on the left window, where the cursor was last seen.
2572 *
2573 * After that, we inject one finger down onto the right window, and then a second finger down onto
2574 * the left window.
2575 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2576 * window (first), and then another on the left window (second).
2577 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2578 * In the buggy implementation, second finger down on the left window would cause a crash.
2579 */
2580TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2581 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2582 sp<FakeWindowHandle> leftWindow =
2583 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2584 leftWindow->setFrame(Rect(0, 0, 200, 200));
2585
2586 sp<FakeWindowHandle> rightWindow =
2587 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2588 rightWindow->setFrame(Rect(200, 0, 400, 200));
2589
2590 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2591
2592 const int32_t mouseDeviceId = 6;
2593 const int32_t touchDeviceId = 4;
2594 // Hover over the left window. Keep the cursor there.
2595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2596 injectMotionEvent(mDispatcher,
2597 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2598 AINPUT_SOURCE_MOUSE)
2599 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002600 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002601 .x(50)
2602 .y(50))
2603 .build()));
2604 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2605
2606 // Tap on left window
2607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2608 injectMotionEvent(mDispatcher,
2609 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2610 AINPUT_SOURCE_TOUCHSCREEN)
2611 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002612 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002613 .x(100)
2614 .y(100))
2615 .build()));
2616
2617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2618 injectMotionEvent(mDispatcher,
2619 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2620 AINPUT_SOURCE_TOUCHSCREEN)
2621 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002622 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002623 .x(100)
2624 .y(100))
2625 .build()));
2626 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2627 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2628 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2629
2630 // First finger down on right window
2631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2632 injectMotionEvent(mDispatcher,
2633 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2634 AINPUT_SOURCE_TOUCHSCREEN)
2635 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002636 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002637 .x(300)
2638 .y(100))
2639 .build()));
2640 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2641
2642 // Second finger down on the left window
2643 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2644 injectMotionEvent(mDispatcher,
2645 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2646 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002647 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002648 .x(300)
2649 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002650 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002651 .x(100)
2652 .y(100))
2653 .build()));
2654 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2655 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2656
2657 // No more events
2658 leftWindow->assertNoEvents();
2659 rightWindow->assertNoEvents();
2660}
2661
2662/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002663 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2664 * While the touch is down, new hover events from the stylus device should be ignored. After the
2665 * touch is gone, stylus hovering should start working again.
2666 */
2667TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2668 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2669 sp<FakeWindowHandle> window =
2670 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2671 window->setFrame(Rect(0, 0, 200, 200));
2672
2673 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2674
2675 const int32_t stylusDeviceId = 5;
2676 const int32_t touchDeviceId = 4;
2677 // Start hovering with stylus
2678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2679 injectMotionEvent(mDispatcher,
2680 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2681 AINPUT_SOURCE_STYLUS)
2682 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002683 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002684 .x(50)
2685 .y(50))
2686 .build()));
2687 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2688
2689 // Finger down on the window
2690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2691 injectMotionEvent(mDispatcher,
2692 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2693 AINPUT_SOURCE_TOUCHSCREEN)
2694 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002695 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002696 .x(100)
2697 .y(100))
2698 .build()));
2699 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2700 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2701
2702 // Try to continue hovering with stylus. Since we are already down, injection should fail
2703 ASSERT_EQ(InputEventInjectionResult::FAILED,
2704 injectMotionEvent(mDispatcher,
2705 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2706 AINPUT_SOURCE_STYLUS)
2707 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002708 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002709 .x(50)
2710 .y(50))
2711 .build()));
2712 // No event should be sent. This event should be ignored because a pointer from another device
2713 // is already down.
2714
2715 // Lift up the finger
2716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2717 injectMotionEvent(mDispatcher,
2718 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2719 AINPUT_SOURCE_TOUCHSCREEN)
2720 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002721 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002722 .x(100)
2723 .y(100))
2724 .build()));
2725 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2726
2727 // Now that the touch is gone, stylus hovering should start working again
2728 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2729 injectMotionEvent(mDispatcher,
2730 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2731 AINPUT_SOURCE_STYLUS)
2732 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002733 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002734 .x(50)
2735 .y(50))
2736 .build()));
2737 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2738 // No more events
2739 window->assertNoEvents();
2740}
2741
2742/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002743 * A spy window above a window with no input channel.
2744 * Start hovering with a stylus device, and then tap with it.
2745 * Ensure spy window receives the entire sequence.
2746 */
2747TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2748 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2749 sp<FakeWindowHandle> spyWindow =
2750 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2751 spyWindow->setFrame(Rect(0, 0, 200, 200));
2752 spyWindow->setTrustedOverlay(true);
2753 spyWindow->setSpy(true);
2754 sp<FakeWindowHandle> window =
2755 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2756 window->setNoInputChannel(true);
2757 window->setFrame(Rect(0, 0, 200, 200));
2758
2759 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2760
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002761 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002762 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2763 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2764 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002765 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2766 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002767 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2768 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2769 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002770 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2771
2772 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002773 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2774 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2775 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002776 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2777
2778 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002779 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2780 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2781 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002782 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2783
2784 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002785 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2786 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2787 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002788 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2789 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002790 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2791 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2792 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002793 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2794
2795 // No more events
2796 spyWindow->assertNoEvents();
2797 window->assertNoEvents();
2798}
2799
2800/**
2801 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2802 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2803 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2804 * While the mouse is down, new move events from the touch device should be ignored.
2805 */
2806TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2807 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2808 sp<FakeWindowHandle> spyWindow =
2809 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2810 spyWindow->setFrame(Rect(0, 0, 200, 200));
2811 spyWindow->setTrustedOverlay(true);
2812 spyWindow->setSpy(true);
2813 sp<FakeWindowHandle> window =
2814 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2815 window->setFrame(Rect(0, 0, 200, 200));
2816
2817 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2818
2819 const int32_t mouseDeviceId = 7;
2820 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002821
2822 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002823 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2824 .deviceId(mouseDeviceId)
2825 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2826 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002827 spyWindow->consumeMotionEvent(
2828 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2829 window->consumeMotionEvent(
2830 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2831
2832 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002833 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2834 .deviceId(touchDeviceId)
2835 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2836 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002837 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2838 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2839 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2840 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2841
Prabir Pradhan678438e2023-04-13 19:32:51 +00002842 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2843 .deviceId(touchDeviceId)
2844 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2845 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002846 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2847 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2848
2849 // Pilfer the stream
2850 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2851 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2852
Prabir Pradhan678438e2023-04-13 19:32:51 +00002853 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2854 .deviceId(touchDeviceId)
2855 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2856 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002857 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2858
2859 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002860 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2861 .deviceId(mouseDeviceId)
2862 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2863 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2864 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002865
2866 spyWindow->consumeMotionEvent(
2867 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2868 spyWindow->consumeMotionEvent(
2869 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2870 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2871
Prabir Pradhan678438e2023-04-13 19:32:51 +00002872 mDispatcher->notifyMotion(
2873 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2874 .deviceId(mouseDeviceId)
2875 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2876 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2877 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2878 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002879 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2880 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2881
2882 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002883 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2884 .deviceId(mouseDeviceId)
2885 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2886 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2887 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002888 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2889 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2890
2891 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002892 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2893 .deviceId(touchDeviceId)
2894 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2895 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002896
2897 // No more events
2898 spyWindow->assertNoEvents();
2899 window->assertNoEvents();
2900}
2901
2902/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002903 * On the display, have a single window, and also an area where there's no window.
2904 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2905 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2906 */
2907TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2908 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2909 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002910 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002911
2912 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002913
2914 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002915 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002916
2917 mDispatcher->waitForIdle();
2918 window->assertNoEvents();
2919
2920 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002921 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002922 mDispatcher->waitForIdle();
2923 window->consumeMotionDown();
2924}
2925
2926/**
2927 * Same test as above, but instead of touching the empty space, the first touch goes to
2928 * non-touchable window.
2929 */
2930TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2931 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2932 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002933 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002934 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2935 window1->setTouchable(false);
2936 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002937 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002938 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2939
2940 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2941
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002942 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002943 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002944
2945 mDispatcher->waitForIdle();
2946 window1->assertNoEvents();
2947 window2->assertNoEvents();
2948
2949 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002950 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002951 mDispatcher->waitForIdle();
2952 window2->consumeMotionDown();
2953}
2954
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002955/**
2956 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2957 * to the event time of the first ACTION_DOWN sent to the particular window.
2958 */
2959TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2960 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2961 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002962 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002963 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2964 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002965 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002966 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2967
2968 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2969
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002970 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002971 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002972
2973 mDispatcher->waitForIdle();
2974 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002975 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002976 window2->assertNoEvents();
2977 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
2978 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
2979 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
2980
2981 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002982 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002983 mDispatcher->waitForIdle();
2984 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002985 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002986 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
2987 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
2988 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
2989 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
2990
2991 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002992 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002993 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002994 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002995
2996 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002997 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002998 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002999 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003000
3001 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3002 window1->consumeMotionMove();
3003 window1->assertNoEvents();
3004
3005 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003006 mDispatcher->notifyMotion(
3007 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003008 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003009 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003010
Prabir Pradhan678438e2023-04-13 19:32:51 +00003011 mDispatcher->notifyMotion(
3012 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003013 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003014 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003015}
3016
Garfield Tandf26e862020-07-01 20:18:19 -07003017TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003018 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003019 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003020 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003021 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003022 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003023 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003024 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003025
3026 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3027
3028 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3029
3030 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003032 injectMotionEvent(mDispatcher,
3033 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3034 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003035 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003036 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003037 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003038
3039 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003040 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003041 injectMotionEvent(mDispatcher,
3042 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3043 AINPUT_SOURCE_MOUSE)
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 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3047 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003048
3049 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003051 injectMotionEvent(mDispatcher,
3052 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3053 .buttonState(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 Vishniakouf372b812023-02-14 18:06:51 -08003056 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3057 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003058
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003060 injectMotionEvent(mDispatcher,
3061 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3062 AINPUT_SOURCE_MOUSE)
3063 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3064 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003065 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003066 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003067 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003068
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003070 injectMotionEvent(mDispatcher,
3071 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3072 AINPUT_SOURCE_MOUSE)
3073 .buttonState(0)
3074 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003075 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003076 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003077 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003078
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003080 injectMotionEvent(mDispatcher,
3081 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3082 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003083 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003084 .build()));
3085 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3086
3087 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003089 injectMotionEvent(mDispatcher,
3090 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3091 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003092 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003093 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003094 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003095
3096 // No more events
3097 windowLeft->assertNoEvents();
3098 windowRight->assertNoEvents();
3099}
3100
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003101/**
3102 * Put two fingers down (and don't release them) and click the mouse button.
3103 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3104 * currently active gesture should be canceled, and the new one should proceed.
3105 */
3106TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3107 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3108 sp<FakeWindowHandle> window =
3109 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3110 window->setFrame(Rect(0, 0, 600, 800));
3111
3112 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3113
3114 const int32_t touchDeviceId = 4;
3115 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003116
3117 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003118 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3119 .deviceId(touchDeviceId)
3120 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3121 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003122
Prabir Pradhan678438e2023-04-13 19:32:51 +00003123 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3124 .deviceId(touchDeviceId)
3125 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3126 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3127 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003128 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3129 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3130
3131 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003132 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3133 .deviceId(mouseDeviceId)
3134 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3135 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3136 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003137 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3138 WithPointerCount(2u)));
3139 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3140
Prabir Pradhan678438e2023-04-13 19:32:51 +00003141 mDispatcher->notifyMotion(
3142 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3143 .deviceId(mouseDeviceId)
3144 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3145 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3146 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3147 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003148 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3149
3150 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3151 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003152 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3153 .deviceId(touchDeviceId)
3154 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3155 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3156 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003157 window->assertNoEvents();
3158}
3159
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003160TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3161 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3162
3163 sp<FakeWindowHandle> spyWindow =
3164 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3165 spyWindow->setFrame(Rect(0, 0, 600, 800));
3166 spyWindow->setTrustedOverlay(true);
3167 spyWindow->setSpy(true);
3168 sp<FakeWindowHandle> window =
3169 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3170 window->setFrame(Rect(0, 0, 600, 800));
3171
3172 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3173 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3174
3175 // Send mouse cursor to the window
3176 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3177 injectMotionEvent(mDispatcher,
3178 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3179 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003180 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003181 .x(100)
3182 .y(100))
3183 .build()));
3184
3185 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3186 WithSource(AINPUT_SOURCE_MOUSE)));
3187 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3188 WithSource(AINPUT_SOURCE_MOUSE)));
3189
3190 window->assertNoEvents();
3191 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003192}
3193
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003194TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3195 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3196
3197 sp<FakeWindowHandle> spyWindow =
3198 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3199 spyWindow->setFrame(Rect(0, 0, 600, 800));
3200 spyWindow->setTrustedOverlay(true);
3201 spyWindow->setSpy(true);
3202 sp<FakeWindowHandle> window =
3203 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3204 window->setFrame(Rect(0, 0, 600, 800));
3205
3206 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3207 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3208
3209 // Send mouse cursor to the window
3210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3211 injectMotionEvent(mDispatcher,
3212 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3213 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003214 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003215 .x(100)
3216 .y(100))
3217 .build()));
3218
3219 // Move mouse cursor
3220 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3221 injectMotionEvent(mDispatcher,
3222 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3223 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003224 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003225 .x(110)
3226 .y(110))
3227 .build()));
3228
3229 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3230 WithSource(AINPUT_SOURCE_MOUSE)));
3231 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3232 WithSource(AINPUT_SOURCE_MOUSE)));
3233 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3234 WithSource(AINPUT_SOURCE_MOUSE)));
3235 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3236 WithSource(AINPUT_SOURCE_MOUSE)));
3237 // Touch down on the window
3238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3239 injectMotionEvent(mDispatcher,
3240 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3241 AINPUT_SOURCE_TOUCHSCREEN)
3242 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003243 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003244 .x(200)
3245 .y(200))
3246 .build()));
3247 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3248 WithSource(AINPUT_SOURCE_MOUSE)));
3249 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3250 WithSource(AINPUT_SOURCE_MOUSE)));
3251 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3252 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3253 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3254 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3255
3256 // pilfer the motion, retaining the gesture on the spy window.
3257 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3258 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3259 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3260
3261 // Touch UP on the window
3262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3263 injectMotionEvent(mDispatcher,
3264 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3265 AINPUT_SOURCE_TOUCHSCREEN)
3266 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003267 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003268 .x(200)
3269 .y(200))
3270 .build()));
3271 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3272 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3273
3274 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3275 // to send a new gesture. It should again go to both windows (spy and the window below), just
3276 // like the first gesture did, before pilfering. The window configuration has not changed.
3277
3278 // One more tap - DOWN
3279 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3280 injectMotionEvent(mDispatcher,
3281 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3282 AINPUT_SOURCE_TOUCHSCREEN)
3283 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003284 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003285 .x(250)
3286 .y(250))
3287 .build()));
3288 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3289 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3290 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3291 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3292
3293 // Touch UP on the window
3294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3295 injectMotionEvent(mDispatcher,
3296 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3297 AINPUT_SOURCE_TOUCHSCREEN)
3298 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003299 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003300 .x(250)
3301 .y(250))
3302 .build()));
3303 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3304 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3305 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3306 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3307
3308 window->assertNoEvents();
3309 spyWindow->assertNoEvents();
3310}
3311
Garfield Tandf26e862020-07-01 20:18:19 -07003312// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3313// directly in this test.
3314TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003315 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003316 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003317 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003318 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003319
3320 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3321
3322 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3323
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003324 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003325 injectMotionEvent(mDispatcher,
3326 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3327 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003328 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003329 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003330 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003331 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003332 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003333 injectMotionEvent(mDispatcher,
3334 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3335 .buttonState(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 Vishniakouf372b812023-02-14 18:06:51 -08003338 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3339 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003340
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003341 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003342 injectMotionEvent(mDispatcher,
3343 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3344 AINPUT_SOURCE_MOUSE)
3345 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3346 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003347 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003348 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003349 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003350
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003351 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003352 injectMotionEvent(mDispatcher,
3353 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3354 AINPUT_SOURCE_MOUSE)
3355 .buttonState(0)
3356 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003357 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003358 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003359 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003360
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003361 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003362 injectMotionEvent(mDispatcher,
3363 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3364 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003365 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003366 .build()));
3367 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3368
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003369 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3370 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3371 ASSERT_EQ(InputEventInjectionResult::FAILED,
Garfield Tandf26e862020-07-01 20:18:19 -07003372 injectMotionEvent(mDispatcher,
3373 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3374 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003375 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003376 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003377 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003378}
3379
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003380/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003381 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3382 * is generated.
3383 */
3384TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3385 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3386 sp<FakeWindowHandle> window =
3387 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3388 window->setFrame(Rect(0, 0, 1200, 800));
3389
3390 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3391
3392 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3393
3394 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3395 injectMotionEvent(mDispatcher,
3396 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3397 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003398 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003399 .x(300)
3400 .y(400))
3401 .build()));
3402 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3403
3404 // Remove the window, but keep the channel.
3405 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3406 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3407}
3408
3409/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003410 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3411 */
3412TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3413 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3414 sp<FakeWindowHandle> window =
3415 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3416 window->setFrame(Rect(0, 0, 100, 100));
3417
3418 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3419
3420 const int32_t mouseDeviceId = 7;
3421 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003422
3423 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003424 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3425 .deviceId(mouseDeviceId)
3426 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3427 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003428 window->consumeMotionEvent(
3429 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3430
3431 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003432 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3433 .deviceId(touchDeviceId)
3434 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3435 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003436
3437 window->consumeMotionEvent(
3438 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3439 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3440}
3441
3442/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003443 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003444 * The tap causes a HOVER_EXIT event to be generated because the current event
3445 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003446 */
3447TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3448 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3449 sp<FakeWindowHandle> window =
3450 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3451 window->setFrame(Rect(0, 0, 100, 100));
3452
3453 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3454
3455 // Inject a hover_move from mouse.
3456 NotifyMotionArgs motionArgs =
3457 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3458 ADISPLAY_ID_DEFAULT, {{50, 50}});
3459 motionArgs.xCursorPosition = 50;
3460 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003461 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003462 ASSERT_NO_FATAL_FAILURE(
3463 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3464 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003465
3466 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003467 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3468 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3469 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003470 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003471 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3472 WithSource(AINPUT_SOURCE_MOUSE))));
3473
3474 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003475 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3476 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3477
Prabir Pradhan678438e2023-04-13 19:32:51 +00003478 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3479 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003480 ASSERT_NO_FATAL_FAILURE(
3481 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3482 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3483}
3484
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003485TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3486 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3487 sp<FakeWindowHandle> windowDefaultDisplay =
3488 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3489 ADISPLAY_ID_DEFAULT);
3490 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3491 sp<FakeWindowHandle> windowSecondDisplay =
3492 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3493 SECOND_DISPLAY_ID);
3494 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3495
3496 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3497 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3498
3499 // Set cursor position in window in default display and check that hover enter and move
3500 // events are generated.
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(300)
3508 .y(600))
3509 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003510 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003511
3512 // Remove all windows in secondary display and check that no event happens on window in
3513 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003514 mDispatcher->setInputWindows(
3515 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003516 windowDefaultDisplay->assertNoEvents();
3517
3518 // Move cursor position in window in default display and check that only hover move
3519 // event is generated and not hover enter event.
3520 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3521 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3523 injectMotionEvent(mDispatcher,
3524 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3525 AINPUT_SOURCE_MOUSE)
3526 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003527 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003528 .x(400)
3529 .y(700))
3530 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003531 windowDefaultDisplay->consumeMotionEvent(
3532 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3533 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003534 windowDefaultDisplay->assertNoEvents();
3535}
3536
Garfield Tan00f511d2019-06-12 16:55:40 -07003537TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003538 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003539
3540 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003541 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003542 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003543 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003544 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003545 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003546
3547 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3548
Arthur Hung72d8dc32020-03-28 00:48:39 +00003549 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003550
3551 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3552 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003553 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003554 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003555 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003556 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003557 windowRight->assertNoEvents();
3558}
3559
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003560TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003561 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003562 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3563 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003564 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003565
Arthur Hung72d8dc32020-03-28 00:48:39 +00003566 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003567 setFocusedWindow(window);
3568
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003569 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003570
Prabir Pradhan678438e2023-04-13 19:32:51 +00003571 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003572
3573 // Window should receive key down event.
3574 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3575
3576 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3577 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003578 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003579 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003580 AKEY_EVENT_FLAG_CANCELED);
3581}
3582
3583TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003584 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003585 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3586 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003587
Arthur Hung72d8dc32020-03-28 00:48:39 +00003588 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003589
Prabir Pradhan678438e2023-04-13 19:32:51 +00003590 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3591 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003592
3593 // Window should receive motion down event.
3594 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3595
3596 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3597 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003598 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003599 window->consumeMotionEvent(
3600 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003601}
3602
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003603TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3604 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3605 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3606 "Fake Window", ADISPLAY_ID_DEFAULT);
3607
3608 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3609
3610 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3611 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3612 .build());
3613
3614 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3615
3616 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3617 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3618 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3619
3620 // After the device has been reset, a new hovering stream can be sent to the window
3621 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3622 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3623 .build());
3624 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3625}
3626
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003627TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3628 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003629 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3630 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003631 window->setFocusable(true);
3632
3633 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3634 setFocusedWindow(window);
3635
3636 window->consumeFocusEvent(true);
3637
Prabir Pradhan678438e2023-04-13 19:32:51 +00003638 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003639 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3640 const nsecs_t injectTime = keyArgs.eventTime;
3641 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003642 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003643 // The dispatching time should be always greater than or equal to intercept key timeout.
3644 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3645 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3646 std::chrono::nanoseconds(interceptKeyTimeout).count());
3647}
3648
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003649/**
3650 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
3651 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003652TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3653 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003654 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3655 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003656 window->setFocusable(true);
3657
3658 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3659 setFocusedWindow(window);
3660
3661 window->consumeFocusEvent(true);
3662
Prabir Pradhan678438e2023-04-13 19:32:51 +00003663 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003664 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003665
3666 // Set a value that's significantly larger than the default consumption timeout. If the
3667 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
3668 mFakePolicy->setInterceptKeyTimeout(600ms);
3669 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
3670 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003671 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3672}
3673
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003674/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003675 * Two windows. First is a regular window. Second does not overlap with the first, and has
3676 * WATCH_OUTSIDE_TOUCH.
3677 * Both windows are owned by the same UID.
3678 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3679 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3680 */
3681TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3682 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3683 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3684 "First Window", ADISPLAY_ID_DEFAULT);
3685 window->setFrame(Rect{0, 0, 100, 100});
3686
3687 sp<FakeWindowHandle> outsideWindow =
3688 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3689 ADISPLAY_ID_DEFAULT);
3690 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3691 outsideWindow->setWatchOutsideTouch(true);
3692 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3693 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3694
3695 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003696 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3697 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3698 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003699 window->consumeMotionDown();
3700 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3701 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3702 outsideWindow->consumeMotionEvent(
3703 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3704}
3705
3706/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003707 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3708 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3709 * ACTION_OUTSIDE event is sent per gesture.
3710 */
3711TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3712 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3713 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003714 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3715 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003716 window->setWatchOutsideTouch(true);
3717 window->setFrame(Rect{0, 0, 100, 100});
3718 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003719 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3720 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003721 secondWindow->setFrame(Rect{100, 100, 200, 200});
3722 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003723 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3724 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003725 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3726 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3727
3728 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003729 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3730 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3731 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003732 window->assertNoEvents();
3733 secondWindow->assertNoEvents();
3734
3735 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3736 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003737 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3738 ADISPLAY_ID_DEFAULT,
3739 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003740 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3741 window->consumeMotionEvent(
3742 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003743 secondWindow->consumeMotionDown();
3744 thirdWindow->assertNoEvents();
3745
3746 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3747 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003748 mDispatcher->notifyMotion(
3749 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3750 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003751 window->assertNoEvents();
3752 secondWindow->consumeMotionMove();
3753 thirdWindow->consumeMotionDown();
3754}
3755
Prabir Pradhan814fe082022-07-22 20:22:18 +00003756TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3757 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003758 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3759 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003760 window->setFocusable(true);
3761
Patrick Williamsd828f302023-04-28 17:52:08 -05003762 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003763 setFocusedWindow(window);
3764
3765 window->consumeFocusEvent(true);
3766
Prabir Pradhan678438e2023-04-13 19:32:51 +00003767 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3768 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3769 mDispatcher->notifyKey(keyDown);
3770 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003771
3772 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3773 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3774
3775 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05003776 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003777
3778 window->consumeFocusEvent(false);
3779
Prabir Pradhan678438e2023-04-13 19:32:51 +00003780 mDispatcher->notifyKey(keyDown);
3781 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003782 window->assertNoEvents();
3783}
3784
Arthur Hung96483742022-11-15 03:30:48 +00003785TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3786 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3787 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3788 "Fake Window", ADISPLAY_ID_DEFAULT);
3789 // Ensure window is non-split and have some transform.
3790 window->setPreventSplitting(true);
3791 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05003792 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003793
3794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3795 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3796 {50, 50}))
3797 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3798 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3799
3800 const MotionEvent secondFingerDownEvent =
3801 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3802 .displayId(ADISPLAY_ID_DEFAULT)
3803 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003804 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3805 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003806 .build();
3807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3808 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3809 InputEventInjectionSync::WAIT_FOR_RESULT))
3810 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3811
3812 const MotionEvent* event = window->consumeMotion();
3813 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3814 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3815 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3816 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3817 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3818}
3819
Harry Cuttsb166c002023-05-09 13:06:05 +00003820TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
3821 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3822 sp<FakeWindowHandle> window =
3823 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3824 window->setFrame(Rect(0, 0, 400, 400));
3825 sp<FakeWindowHandle> trustedOverlay =
3826 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
3827 ADISPLAY_ID_DEFAULT);
3828 trustedOverlay->setSpy(true);
3829 trustedOverlay->setTrustedOverlay(true);
3830
3831 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {trustedOverlay, window}}});
3832
3833 // Start a three-finger touchpad swipe
3834 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3835 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3836 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3837 .build());
3838 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3839 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3840 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3841 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3842 .build());
3843 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3844 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3845 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3846 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3847 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3848 .build());
3849
3850 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3851 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3852 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
3853
3854 // Move the swipe a bit
3855 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3856 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3857 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3858 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3859 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3860 .build());
3861
3862 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3863
3864 // End the swipe
3865 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3866 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3867 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3868 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3869 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3870 .build());
3871 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3872 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3873 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3874 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3875 .build());
3876 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3877 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3878 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3879 .build());
3880
3881 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
3882 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3883 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
3884
3885 window->assertNoEvents();
3886}
3887
3888TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
3889 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3890 sp<FakeWindowHandle> window =
3891 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3892 window->setFrame(Rect(0, 0, 400, 400));
3893 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3894
3895 // Start a three-finger touchpad swipe
3896 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3897 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3898 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3899 .build());
3900 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3901 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3902 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3903 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3904 .build());
3905 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3906 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3907 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3908 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3909 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3910 .build());
3911
3912 // Move the swipe a bit
3913 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3914 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3915 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3916 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3917 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3918 .build());
3919
3920 // End the swipe
3921 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3922 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3923 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3924 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3925 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3926 .build());
3927 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3928 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3929 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3930 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3931 .build());
3932 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3933 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3934 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3935 .build());
3936
3937 window->assertNoEvents();
3938}
3939
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003940/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003941 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
3942 * the first pointer.
3943 * Ensure that the second pointer is not sent to the window.
3944 *
3945 * The subsequent gesture should be correctly delivered to the window.
3946 */
3947TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
3948 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3949 sp<FakeWindowHandle> window =
3950 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3951 window->setFrame(Rect(0, 0, 400, 400));
3952 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3953
3954 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
3955 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3956 .downTime(baseTime + 10)
3957 .eventTime(baseTime + 10)
3958 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3959 .build());
3960
3961 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3962
3963 // We need a new window object for the same window, because dispatcher will store objects by
3964 // reference. That means that the testing code and the dispatcher will refer to the same shared
3965 // object. Calling window->setTransform here would affect dispatcher's comparison
3966 // of the old window to the new window, since both the old window and the new window would be
3967 // updated to the same value.
3968 sp<FakeWindowHandle> windowDup = window->duplicate();
3969
3970 // Change the transform so that the orientation is now different from original.
3971 windowDup->setWindowTransform(0, -1, 1, 0);
3972
3973 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDup}}});
3974
3975 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3976
3977 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3978 .downTime(baseTime + 10)
3979 .eventTime(baseTime + 30)
3980 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3981 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3982 .build());
3983
3984 // Finish the gesture and start a new one. Ensure the new gesture is sent to the window
3985 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
3986 .downTime(baseTime + 10)
3987 .eventTime(baseTime + 40)
3988 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3989 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3990 .build());
3991 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3992 .downTime(baseTime + 10)
3993 .eventTime(baseTime + 50)
3994 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3995 .build());
3996
3997 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3998 .downTime(baseTime + 60)
3999 .eventTime(baseTime + 60)
4000 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4001 .build());
4002
4003 windowDup->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4004}
4005
4006/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004007 * Ensure the correct coordinate spaces are used by InputDispatcher.
4008 *
4009 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4010 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4011 * space.
4012 */
4013class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4014public:
4015 void SetUp() override {
4016 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004017 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004018 }
4019
4020 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4021 gui::DisplayInfo info;
4022 info.displayId = displayId;
4023 info.transform = transform;
4024 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004025 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004026 }
4027
4028 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4029 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004030 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004031 }
4032
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004033 void removeAllWindowsAndDisplays() {
4034 mDisplayInfos.clear();
4035 mWindowInfos.clear();
4036 }
4037
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004038 // Set up a test scenario where the display has a scaled projection and there are two windows
4039 // on the display.
4040 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4041 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4042 // respectively.
4043 ui::Transform displayTransform;
4044 displayTransform.set(2, 0, 0, 4);
4045 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4046
4047 std::shared_ptr<FakeApplicationHandle> application =
4048 std::make_shared<FakeApplicationHandle>();
4049
4050 // Add two windows to the display. Their frames are represented in the display space.
4051 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004052 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4053 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004054 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4055 addWindow(firstWindow);
4056
4057 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004058 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4059 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004060 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4061 addWindow(secondWindow);
4062 return {std::move(firstWindow), std::move(secondWindow)};
4063 }
4064
4065private:
4066 std::vector<gui::DisplayInfo> mDisplayInfos;
4067 std::vector<gui::WindowInfo> mWindowInfos;
4068};
4069
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004070TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004071 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4072 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004073 // selected so that if the hit test was performed with the point and the bounds being in
4074 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004075 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4076 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4077 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004078
4079 firstWindow->consumeMotionDown();
4080 secondWindow->assertNoEvents();
4081}
4082
4083// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4084// the event should be treated as being in the logical display space.
4085TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4086 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4087 // Send down to the first window. The point is represented in the logical display space. The
4088 // point is selected so that if the hit test was done in logical display space, then it would
4089 // end up in the incorrect window.
4090 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4091 PointF{75 * 2, 55 * 4});
4092
4093 firstWindow->consumeMotionDown();
4094 secondWindow->assertNoEvents();
4095}
4096
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004097// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4098// event should be treated as being in the logical display space.
4099TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4100 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4101
4102 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4103 ui::Transform injectedEventTransform;
4104 injectedEventTransform.set(matrix);
4105 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4106 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4107
4108 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4109 .displayId(ADISPLAY_ID_DEFAULT)
4110 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004111 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004112 .x(untransformedPoint.x)
4113 .y(untransformedPoint.y))
4114 .build();
4115 event.transform(matrix);
4116
4117 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
4118 InputEventInjectionSync::WAIT_FOR_RESULT);
4119
4120 firstWindow->consumeMotionDown();
4121 secondWindow->assertNoEvents();
4122}
4123
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004124TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4125 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4126
4127 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004128 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4129 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4130 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004131
4132 firstWindow->assertNoEvents();
4133 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004134 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004135 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4136
4137 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4138 EXPECT_EQ(300, event->getRawX(0));
4139 EXPECT_EQ(880, event->getRawY(0));
4140
4141 // Ensure that the x and y values are in the window's coordinate space.
4142 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4143 // the logical display space. This will be the origin of the window space.
4144 EXPECT_EQ(100, event->getX(0));
4145 EXPECT_EQ(80, event->getY(0));
4146}
4147
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004148/** Ensure consistent behavior of InputDispatcher in all orientations. */
4149class InputDispatcherDisplayOrientationFixture
4150 : public InputDispatcherDisplayProjectionTest,
4151 public ::testing::WithParamInterface<ui::Rotation> {};
4152
4153// This test verifies the touchable region of a window for all rotations of the display by tapping
4154// in different locations on the display, specifically points close to the four corners of a
4155// window.
4156TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4157 constexpr static int32_t displayWidth = 400;
4158 constexpr static int32_t displayHeight = 800;
4159
4160 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4161
4162 const auto rotation = GetParam();
4163
4164 // Set up the display with the specified rotation.
4165 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4166 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4167 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4168 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4169 logicalDisplayWidth, logicalDisplayHeight);
4170 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4171
4172 // Create a window with its bounds determined in the logical display.
4173 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4174 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4175 sp<FakeWindowHandle> window =
4176 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4177 window->setFrame(frameInDisplay, displayTransform);
4178 addWindow(window);
4179
4180 // The following points in logical display space should be inside the window.
4181 static const std::array<vec2, 4> insidePoints{
4182 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4183 for (const auto pointInsideWindow : insidePoints) {
4184 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4185 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004186 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4187 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4188 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004189 window->consumeMotionDown();
4190
Prabir Pradhan678438e2023-04-13 19:32:51 +00004191 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4192 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4193 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004194 window->consumeMotionUp();
4195 }
4196
4197 // The following points in logical display space should be outside the window.
4198 static const std::array<vec2, 5> outsidePoints{
4199 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4200 for (const auto pointOutsideWindow : outsidePoints) {
4201 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4202 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004203 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4204 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4205 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004206
Prabir Pradhan678438e2023-04-13 19:32:51 +00004207 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4208 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4209 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004210 }
4211 window->assertNoEvents();
4212}
4213
4214// Run the precision tests for all rotations.
4215INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4216 InputDispatcherDisplayOrientationFixture,
4217 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4218 ui::ROTATION_270),
4219 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4220 return ftl::enum_string(testParamInfo.param);
4221 });
4222
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004223using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4224 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004225
4226class TransferTouchFixture : public InputDispatcherTest,
4227 public ::testing::WithParamInterface<TransferFunction> {};
4228
4229TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004230 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004231
4232 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004233 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004234 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4235 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004236 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004237 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004238 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4239 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004240 sp<FakeWindowHandle> wallpaper =
4241 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4242 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004243 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004244 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004245
4246 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004247 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4248 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004249
Svet Ganov5d3bc372020-01-26 23:11:07 -08004250 // Only the first window should get the down event
4251 firstWindow->consumeMotionDown();
4252 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004253 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004254
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004255 // Transfer touch to the second window
4256 TransferFunction f = GetParam();
4257 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4258 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004259 // The first window gets cancel and the second gets down
4260 firstWindow->consumeMotionCancel();
4261 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004262 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004263
4264 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004265 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4266 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004267 // The first window gets no events and the second gets up
4268 firstWindow->assertNoEvents();
4269 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004270 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004271}
4272
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004273/**
4274 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4275 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4276 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4277 * natural to the user.
4278 * In this test, we are sending a pointer to both spy window and first window. We then try to
4279 * transfer touch to the second window. The dispatcher should identify the first window as the
4280 * one that should lose the gesture, and therefore the action should be to move the gesture from
4281 * the first window to the second.
4282 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4283 * the other API, as well.
4284 */
4285TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4286 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4287
4288 // Create a couple of windows + a spy window
4289 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004290 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004291 spyWindow->setTrustedOverlay(true);
4292 spyWindow->setSpy(true);
4293 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004294 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004295 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004296 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004297
4298 // Add the windows to the dispatcher
4299 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4300
4301 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004302 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4303 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004304 // Only the first window and spy should get the down event
4305 spyWindow->consumeMotionDown();
4306 firstWindow->consumeMotionDown();
4307
4308 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4309 // if f === 'transferTouch'.
4310 TransferFunction f = GetParam();
4311 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4312 ASSERT_TRUE(success);
4313 // The first window gets cancel and the second gets down
4314 firstWindow->consumeMotionCancel();
4315 secondWindow->consumeMotionDown();
4316
4317 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004318 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4319 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004320 // The first window gets no events and the second+spy get up
4321 firstWindow->assertNoEvents();
4322 spyWindow->consumeMotionUp();
4323 secondWindow->consumeMotionUp();
4324}
4325
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004326TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004327 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004328
4329 PointF touchPoint = {10, 10};
4330
4331 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004332 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004333 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4334 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004335 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004336 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004337 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4338 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004339 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004340
4341 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004342 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004343
4344 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004345 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4346 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4347 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004348 // Only the first window should get the down event
4349 firstWindow->consumeMotionDown();
4350 secondWindow->assertNoEvents();
4351
4352 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004353 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4354 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004355 // Only the first window should get the pointer down event
4356 firstWindow->consumeMotionPointerDown(1);
4357 secondWindow->assertNoEvents();
4358
4359 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004360 TransferFunction f = GetParam();
4361 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4362 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004363 // The first window gets cancel and the second gets down and pointer down
4364 firstWindow->consumeMotionCancel();
4365 secondWindow->consumeMotionDown();
4366 secondWindow->consumeMotionPointerDown(1);
4367
4368 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004369 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4370 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004371 // The first window gets nothing and the second gets pointer up
4372 firstWindow->assertNoEvents();
4373 secondWindow->consumeMotionPointerUp(1);
4374
4375 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004376 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4377 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004378 // The first window gets nothing and the second gets up
4379 firstWindow->assertNoEvents();
4380 secondWindow->consumeMotionUp();
4381}
4382
Arthur Hungc539dbb2022-12-08 07:45:36 +00004383TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4384 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4385
4386 // Create a couple of windows
4387 sp<FakeWindowHandle> firstWindow =
4388 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4389 ADISPLAY_ID_DEFAULT);
4390 firstWindow->setDupTouchToWallpaper(true);
4391 sp<FakeWindowHandle> secondWindow =
4392 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4393 ADISPLAY_ID_DEFAULT);
4394 secondWindow->setDupTouchToWallpaper(true);
4395
4396 sp<FakeWindowHandle> wallpaper1 =
4397 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4398 wallpaper1->setIsWallpaper(true);
4399
4400 sp<FakeWindowHandle> wallpaper2 =
4401 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4402 wallpaper2->setIsWallpaper(true);
4403 // Add the windows to the dispatcher
4404 mDispatcher->setInputWindows(
4405 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4406
4407 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004408 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4409 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004410
4411 // Only the first window should get the down event
4412 firstWindow->consumeMotionDown();
4413 secondWindow->assertNoEvents();
4414 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4415 wallpaper2->assertNoEvents();
4416
4417 // Transfer touch focus to the second window
4418 TransferFunction f = GetParam();
4419 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4420 ASSERT_TRUE(success);
4421
4422 // The first window gets cancel and the second gets down
4423 firstWindow->consumeMotionCancel();
4424 secondWindow->consumeMotionDown();
4425 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4426 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4427
4428 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004429 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4430 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004431 // The first window gets no events and the second gets up
4432 firstWindow->assertNoEvents();
4433 secondWindow->consumeMotionUp();
4434 wallpaper1->assertNoEvents();
4435 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4436}
4437
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004438// For the cases of single pointer touch and two pointers non-split touch, the api's
4439// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4440// for the case where there are multiple pointers split across several windows.
4441INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4442 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004443 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4444 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004445 return dispatcher->transferTouch(destChannelToken,
4446 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004447 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004448 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4449 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004450 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004451 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004452 }));
4453
Svet Ganov5d3bc372020-01-26 23:11:07 -08004454TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004455 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004456
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004457 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004458 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4459 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004460 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004461
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004462 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004463 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4464 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004465 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004466
4467 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004468 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004469
4470 PointF pointInFirst = {300, 200};
4471 PointF pointInSecond = {300, 600};
4472
4473 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004474 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4475 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4476 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004477 // Only the first window should get the down event
4478 firstWindow->consumeMotionDown();
4479 secondWindow->assertNoEvents();
4480
4481 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004482 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4483 ADISPLAY_ID_DEFAULT,
4484 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004485 // The first window gets a move and the second a down
4486 firstWindow->consumeMotionMove();
4487 secondWindow->consumeMotionDown();
4488
4489 // Transfer touch focus to the second window
4490 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4491 // The first window gets cancel and the new gets pointer down (it already saw down)
4492 firstWindow->consumeMotionCancel();
4493 secondWindow->consumeMotionPointerDown(1);
4494
4495 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004496 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4497 ADISPLAY_ID_DEFAULT,
4498 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004499 // The first window gets nothing and the second gets pointer up
4500 firstWindow->assertNoEvents();
4501 secondWindow->consumeMotionPointerUp(1);
4502
4503 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004504 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4505 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004506 // The first window gets nothing and the second gets up
4507 firstWindow->assertNoEvents();
4508 secondWindow->consumeMotionUp();
4509}
4510
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004511// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4512// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4513// touch is not supported, so the touch should continue on those windows and the transferred-to
4514// window should get nothing.
4515TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4516 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4517
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004518 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004519 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4520 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004521 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004522
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004523 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004524 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4525 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004526 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004527
4528 // Add the windows to the dispatcher
4529 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4530
4531 PointF pointInFirst = {300, 200};
4532 PointF pointInSecond = {300, 600};
4533
4534 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004535 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4536 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4537 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004538 // Only the first window should get the down event
4539 firstWindow->consumeMotionDown();
4540 secondWindow->assertNoEvents();
4541
4542 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004543 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4544 ADISPLAY_ID_DEFAULT,
4545 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004546 // The first window gets a move and the second a down
4547 firstWindow->consumeMotionMove();
4548 secondWindow->consumeMotionDown();
4549
4550 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004551 const bool transferred =
4552 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004553 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4554 ASSERT_FALSE(transferred);
4555 firstWindow->assertNoEvents();
4556 secondWindow->assertNoEvents();
4557
4558 // The rest of the dispatch should proceed as normal
4559 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004560 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4561 ADISPLAY_ID_DEFAULT,
4562 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004563 // The first window gets MOVE and the second gets pointer up
4564 firstWindow->consumeMotionMove();
4565 secondWindow->consumeMotionUp();
4566
4567 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004568 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4569 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004570 // The first window gets nothing and the second gets up
4571 firstWindow->consumeMotionUp();
4572 secondWindow->assertNoEvents();
4573}
4574
Arthur Hungabbb9d82021-09-01 14:52:30 +00004575// This case will create two windows and one mirrored window on the default display and mirror
4576// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4577// the windows info of second display before default display.
4578TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4579 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4580 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004581 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004582 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004583 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004584 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004585 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004586
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004587 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004588 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004589
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004590 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004591 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004592
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004593 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004594 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004595
4596 // Update window info, let it find window handle of second display first.
4597 mDispatcher->setInputWindows(
4598 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4599 {ADISPLAY_ID_DEFAULT,
4600 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4601
4602 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4603 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4604 {50, 50}))
4605 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4606
4607 // Window should receive motion event.
4608 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4609
4610 // Transfer touch focus
4611 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4612 secondWindowInPrimary->getToken()));
4613 // The first window gets cancel.
4614 firstWindowInPrimary->consumeMotionCancel();
4615 secondWindowInPrimary->consumeMotionDown();
4616
4617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4618 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4619 ADISPLAY_ID_DEFAULT, {150, 50}))
4620 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4621 firstWindowInPrimary->assertNoEvents();
4622 secondWindowInPrimary->consumeMotionMove();
4623
4624 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4625 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4626 {150, 50}))
4627 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4628 firstWindowInPrimary->assertNoEvents();
4629 secondWindowInPrimary->consumeMotionUp();
4630}
4631
4632// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4633// 'transferTouch' api.
4634TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4635 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4636 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004637 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004638 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004639 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004640 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004641 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004642
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004643 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004644 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004645
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004646 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004647 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004648
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004649 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004650 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004651
4652 // Update window info, let it find window handle of second display first.
4653 mDispatcher->setInputWindows(
4654 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4655 {ADISPLAY_ID_DEFAULT,
4656 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4657
4658 // Touch on second display.
4659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4660 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4661 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4662
4663 // Window should receive motion event.
4664 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4665
4666 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004667 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004668
4669 // The first window gets cancel.
4670 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4671 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4672
4673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4674 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4675 SECOND_DISPLAY_ID, {150, 50}))
4676 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4677 firstWindowInPrimary->assertNoEvents();
4678 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4679
4680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4681 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4682 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4683 firstWindowInPrimary->assertNoEvents();
4684 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4685}
4686
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004687TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004688 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004689 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4690 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004691
Vishnu Nair47074b82020-08-14 11:54:47 -07004692 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004693 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004694 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004695
4696 window->consumeFocusEvent(true);
4697
Prabir Pradhan678438e2023-04-13 19:32:51 +00004698 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004699
4700 // Window should receive key down event.
4701 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004702
4703 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004704 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004705 mFakePolicy->assertUserActivityPoked();
4706}
4707
4708TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4709 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4710 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4711 "Fake Window", ADISPLAY_ID_DEFAULT);
4712
4713 window->setDisableUserActivity(true);
4714 window->setFocusable(true);
4715 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4716 setFocusedWindow(window);
4717
4718 window->consumeFocusEvent(true);
4719
4720 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4721
4722 // Window should receive key down event.
4723 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4724
4725 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004726 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004727 mFakePolicy->assertUserActivityNotPoked();
4728}
4729
4730TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4732 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4733 "Fake Window", ADISPLAY_ID_DEFAULT);
4734
4735 window->setFocusable(true);
4736 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4737 setFocusedWindow(window);
4738
4739 window->consumeFocusEvent(true);
4740
4741 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4742 mDispatcher->waitForIdle();
4743
4744 // System key is not passed down
4745 window->assertNoEvents();
4746
4747 // Should have poked user activity
4748 mFakePolicy->assertUserActivityPoked();
4749}
4750
4751TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4752 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4753 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4754 "Fake Window", ADISPLAY_ID_DEFAULT);
4755
4756 window->setFocusable(true);
4757 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4758 setFocusedWindow(window);
4759
4760 window->consumeFocusEvent(true);
4761
4762 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4763 mDispatcher->waitForIdle();
4764
4765 // System key is not passed down
4766 window->assertNoEvents();
4767
4768 // Should have poked user activity
4769 mFakePolicy->assertUserActivityPoked();
4770}
4771
4772TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4773 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4774 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4775 "Fake Window", ADISPLAY_ID_DEFAULT);
4776
4777 window->setDisableUserActivity(true);
4778 window->setFocusable(true);
4779 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4780 setFocusedWindow(window);
4781
4782 window->consumeFocusEvent(true);
4783
4784 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4785 mDispatcher->waitForIdle();
4786
4787 // System key is not passed down
4788 window->assertNoEvents();
4789
4790 // Should have poked user activity
4791 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004792}
4793
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004794TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
4795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4796 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4797 "Fake Window", ADISPLAY_ID_DEFAULT);
4798
4799 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4800
4801 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4802 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4803 ADISPLAY_ID_DEFAULT, {100, 100}))
4804 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4805
4806 window->consumeMotionEvent(
4807 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
4808
4809 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004810 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004811 mFakePolicy->assertUserActivityPoked();
4812}
4813
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004814TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004815 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004816 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4817 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004818
Arthur Hung72d8dc32020-03-28 00:48:39 +00004819 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004820
Prabir Pradhan678438e2023-04-13 19:32:51 +00004821 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004822 mDispatcher->waitForIdle();
4823
4824 window->assertNoEvents();
4825}
4826
4827// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4828TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004829 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004830 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4831 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004832
Arthur Hung72d8dc32020-03-28 00:48:39 +00004833 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004834
4835 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004836 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004837 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004838 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4839 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004840
4841 // Window should receive only the motion event
4842 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4843 window->assertNoEvents(); // Key event or focus event will not be received
4844}
4845
arthurhungea3f4fc2020-12-21 23:18:53 +08004846TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4847 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4848
arthurhungea3f4fc2020-12-21 23:18:53 +08004849 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004850 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4851 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004852 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004853
arthurhungea3f4fc2020-12-21 23:18:53 +08004854 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004855 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4856 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004857 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004858
4859 // Add the windows to the dispatcher
4860 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4861
4862 PointF pointInFirst = {300, 200};
4863 PointF pointInSecond = {300, 600};
4864
4865 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004866 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4867 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4868 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004869 // Only the first window should get the down event
4870 firstWindow->consumeMotionDown();
4871 secondWindow->assertNoEvents();
4872
4873 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004874 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4875 ADISPLAY_ID_DEFAULT,
4876 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004877 // The first window gets a move and the second a down
4878 firstWindow->consumeMotionMove();
4879 secondWindow->consumeMotionDown();
4880
4881 // Send pointer cancel to the second window
4882 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004883 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004884 {pointInFirst, pointInSecond});
4885 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004886 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004887 // The first window gets move and the second gets cancel.
4888 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4889 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4890
4891 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004892 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4893 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004894 // The first window gets up and the second gets nothing.
4895 firstWindow->consumeMotionUp();
4896 secondWindow->assertNoEvents();
4897}
4898
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004899TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4900 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4901
4902 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004903 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004904 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4905 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4906 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4907 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4908
Harry Cutts33476232023-01-30 19:57:29 +00004909 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004910 window->assertNoEvents();
4911 mDispatcher->waitForIdle();
4912}
4913
chaviwd1c23182019-12-20 18:44:56 -08004914class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004915public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004916 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004917 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004918 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004919 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004920 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004921 }
4922
chaviwd1c23182019-12-20 18:44:56 -08004923 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4924
4925 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004926 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4927 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004928 }
4929
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004930 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4931
4932 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4933
chaviwd1c23182019-12-20 18:44:56 -08004934 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004935 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004936 expectedDisplayId, expectedFlags);
4937 }
4938
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004939 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004940 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004941 expectedDisplayId, expectedFlags);
4942 }
4943
chaviwd1c23182019-12-20 18:44:56 -08004944 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004945 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004946 expectedDisplayId, expectedFlags);
4947 }
4948
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004949 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004950 mInputReceiver->consumeMotionEvent(
4951 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4952 WithDisplayId(expectedDisplayId),
4953 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004954 }
4955
Arthur Hungfbfa5722021-11-16 02:45:54 +00004956 void consumeMotionPointerDown(int32_t pointerIdx) {
4957 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4958 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004959 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004960 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004961 }
4962
Evan Rosky84f07f02021-04-16 10:42:42 -07004963 MotionEvent* consumeMotion() {
4964 InputEvent* event = mInputReceiver->consume();
4965 if (!event) {
4966 ADD_FAILURE() << "No event was produced";
4967 return nullptr;
4968 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004969 if (event->getType() != InputEventType::MOTION) {
4970 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07004971 return nullptr;
4972 }
4973 return static_cast<MotionEvent*>(event);
4974 }
4975
chaviwd1c23182019-12-20 18:44:56 -08004976 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4977
4978private:
4979 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004980};
4981
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004982using InputDispatcherMonitorTest = InputDispatcherTest;
4983
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004984/**
4985 * Two entities that receive touch: A window, and a global monitor.
4986 * The touch goes to the window, and then the window disappears.
4987 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4988 * for the monitor, as well.
4989 * 1. foregroundWindow
4990 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4991 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004992TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004993 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4994 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004995 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004996
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004997 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004998
4999 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5000 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5001 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5002 {100, 200}))
5003 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5004
5005 // Both the foreground window and the global monitor should receive the touch down
5006 window->consumeMotionDown();
5007 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5008
5009 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5010 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5011 ADISPLAY_ID_DEFAULT, {110, 200}))
5012 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5013
5014 window->consumeMotionMove();
5015 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5016
5017 // Now the foreground window goes away
5018 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
5019 window->consumeMotionCancel();
5020 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5021
5022 // If more events come in, there will be no more foreground window to send them to. This will
5023 // cause a cancel for the monitor, as well.
5024 ASSERT_EQ(InputEventInjectionResult::FAILED,
5025 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5026 ADISPLAY_ID_DEFAULT, {120, 200}))
5027 << "Injection should fail because the window was removed";
5028 window->assertNoEvents();
5029 // Global monitor now gets the cancel
5030 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5031}
5032
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005033TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005034 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005035 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5036 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005037 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005038
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005039 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005040
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005042 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005043 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005044 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005045 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005046}
5047
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005048TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5049 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005050
Chris Yea209fde2020-07-22 13:54:51 -07005051 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005052 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5053 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005054 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005055
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005057 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005058 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005059 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005060 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005061
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005062 // Pilfer pointers from the monitor.
5063 // This should not do anything and the window should continue to receive events.
5064 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005065
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005067 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5068 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005069 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005070
5071 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5072 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005073}
5074
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005075TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005076 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005077 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5078 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005079 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5080 window->setWindowOffset(20, 40);
5081 window->setWindowTransform(0, 1, -1, 0);
5082
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005083 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005084
5085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5086 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5087 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5088 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5089 MotionEvent* event = monitor.consumeMotion();
5090 // Even though window has transform, gesture monitor must not.
5091 ASSERT_EQ(ui::Transform(), event->getTransform());
5092}
5093
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005094TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005095 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005096 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005097
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005098 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00005099 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005100 << "Injection should fail if there is a monitor, but no touchable window";
5101 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005102}
5103
chaviw81e2bb92019-12-18 15:03:51 -08005104TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005105 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005106 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5107 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005108
Arthur Hung72d8dc32020-03-28 00:48:39 +00005109 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08005110
5111 NotifyMotionArgs motionArgs =
5112 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5113 ADISPLAY_ID_DEFAULT);
5114
Prabir Pradhan678438e2023-04-13 19:32:51 +00005115 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005116 // Window should receive motion down event.
5117 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5118
5119 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005120 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005121 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5122 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5123 motionArgs.pointerCoords[0].getX() - 10);
5124
Prabir Pradhan678438e2023-04-13 19:32:51 +00005125 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005126 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005127 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005128}
5129
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005130/**
5131 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5132 * the device default right away. In the test scenario, we check both the default value,
5133 * and the action of enabling / disabling.
5134 */
5135TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005136 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005137 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5138 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005139 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005140
5141 // Set focused application.
5142 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005143 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005144
5145 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00005146 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005147 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005148 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005149
5150 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005151 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005152 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005153 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005154
5155 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005156 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005157 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005158 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005159 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005160 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005161 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005162 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005163
5164 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005165 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005166 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005167 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005168
5169 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005170 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005171 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005172 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005173 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005174 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005175 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005176 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005177
5178 window->assertNoEvents();
5179}
5180
Gang Wange9087892020-01-07 12:17:14 -05005181TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005182 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005183 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5184 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005185
5186 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005187 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005188
Arthur Hung72d8dc32020-03-28 00:48:39 +00005189 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005190 setFocusedWindow(window);
5191
Harry Cutts33476232023-01-30 19:57:29 +00005192 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005193
Prabir Pradhan678438e2023-04-13 19:32:51 +00005194 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5195 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005196
5197 InputEvent* event = window->consume();
5198 ASSERT_NE(event, nullptr);
5199
5200 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5201 ASSERT_NE(verified, nullptr);
5202 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5203
5204 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5205 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5206 ASSERT_EQ(keyArgs.source, verified->source);
5207 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5208
5209 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5210
5211 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005212 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005213 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005214 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5215 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5216 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5217 ASSERT_EQ(0, verifiedKey.repeatCount);
5218}
5219
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005220TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005221 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005222 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5223 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005224
5225 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5226
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005227 ui::Transform transform;
5228 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5229
5230 gui::DisplayInfo displayInfo;
5231 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5232 displayInfo.transform = transform;
5233
Patrick Williamsd828f302023-04-28 17:52:08 -05005234 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005235
Prabir Pradhan678438e2023-04-13 19:32:51 +00005236 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005237 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5238 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005239 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005240
5241 InputEvent* event = window->consume();
5242 ASSERT_NE(event, nullptr);
5243
5244 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5245 ASSERT_NE(verified, nullptr);
5246 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5247
5248 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5249 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5250 EXPECT_EQ(motionArgs.source, verified->source);
5251 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5252
5253 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5254
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005255 const vec2 rawXY =
5256 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5257 motionArgs.pointerCoords[0].getXYValue());
5258 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5259 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005260 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005261 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005262 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005263 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5264 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5265}
5266
chaviw09c8d2d2020-08-24 15:48:26 -07005267/**
5268 * Ensure that separate calls to sign the same data are generating the same key.
5269 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5270 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5271 * tests.
5272 */
5273TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5274 KeyEvent event = getTestKeyEvent();
5275 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5276
5277 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5278 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5279 ASSERT_EQ(hmac1, hmac2);
5280}
5281
5282/**
5283 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5284 */
5285TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5286 KeyEvent event = getTestKeyEvent();
5287 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5288 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5289
5290 verifiedEvent.deviceId += 1;
5291 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5292
5293 verifiedEvent.source += 1;
5294 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5295
5296 verifiedEvent.eventTimeNanos += 1;
5297 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5298
5299 verifiedEvent.displayId += 1;
5300 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5301
5302 verifiedEvent.action += 1;
5303 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5304
5305 verifiedEvent.downTimeNanos += 1;
5306 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5307
5308 verifiedEvent.flags += 1;
5309 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5310
5311 verifiedEvent.keyCode += 1;
5312 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5313
5314 verifiedEvent.scanCode += 1;
5315 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5316
5317 verifiedEvent.metaState += 1;
5318 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5319
5320 verifiedEvent.repeatCount += 1;
5321 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5322}
5323
Vishnu Nair958da932020-08-21 17:12:37 -07005324TEST_F(InputDispatcherTest, SetFocusedWindow) {
5325 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5326 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005327 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005328 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005329 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005330 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5331
5332 // Top window is also focusable but is not granted focus.
5333 windowTop->setFocusable(true);
5334 windowSecond->setFocusable(true);
5335 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5336 setFocusedWindow(windowSecond);
5337
5338 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005339 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5340 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005341
5342 // Focused window should receive event.
5343 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5344 windowTop->assertNoEvents();
5345}
5346
5347TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5348 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5349 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005350 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005351 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5352
5353 window->setFocusable(true);
5354 // Release channel for window is no longer valid.
5355 window->releaseChannel();
5356 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5357 setFocusedWindow(window);
5358
5359 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005360 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5361 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005362
5363 // window channel is invalid, so it should not receive any input event.
5364 window->assertNoEvents();
5365}
5366
5367TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5368 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5369 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005370 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005371 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005372 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5373
Vishnu Nair958da932020-08-21 17:12:37 -07005374 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5375 setFocusedWindow(window);
5376
5377 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005378 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5379 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005380
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005381 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005382 window->assertNoEvents();
5383}
5384
5385TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5386 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);
5394 windowSecond->setFocusable(true);
5395 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5396 setFocusedWindow(windowTop);
5397 windowTop->consumeFocusEvent(true);
5398
Chavi Weingarten847e8512023-03-29 00:26:09 +00005399 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5400 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005401 windowSecond->consumeFocusEvent(true);
5402 windowTop->consumeFocusEvent(false);
5403
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005404 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5405 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005406
5407 // Focused window should receive event.
5408 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5409}
5410
Chavi Weingarten847e8512023-03-29 00:26:09 +00005411TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005412 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5413 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005414 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005415 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005416 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005417 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5418
5419 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005420 windowSecond->setFocusable(false);
5421 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005422 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005423 setFocusedWindow(windowTop);
5424 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005425
Chavi Weingarten847e8512023-03-29 00:26:09 +00005426 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5427 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005428
5429 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005430 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005431 windowSecond->assertNoEvents();
5432}
5433
5434TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5435 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5436 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005437 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005438 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005439 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5440 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005441 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5442
5443 window->setFocusable(true);
5444 previousFocusedWindow->setFocusable(true);
5445 window->setVisible(false);
5446 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5447 setFocusedWindow(previousFocusedWindow);
5448 previousFocusedWindow->consumeFocusEvent(true);
5449
5450 // Requesting focus on invisible window takes focus from currently focused window.
5451 setFocusedWindow(window);
5452 previousFocusedWindow->consumeFocusEvent(false);
5453
5454 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005455 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005456 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5457 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005458
5459 // Window does not get focus event or key down.
5460 window->assertNoEvents();
5461
5462 // Window becomes visible.
5463 window->setVisible(true);
5464 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5465
5466 // Window receives focus event.
5467 window->consumeFocusEvent(true);
5468 // Focused window receives key down.
5469 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5470}
5471
Vishnu Nair599f1412021-06-21 10:39:58 -07005472TEST_F(InputDispatcherTest, DisplayRemoved) {
5473 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5474 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005475 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005476 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5477
5478 // window is granted focus.
5479 window->setFocusable(true);
5480 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5481 setFocusedWindow(window);
5482 window->consumeFocusEvent(true);
5483
5484 // When a display is removed window loses focus.
5485 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5486 window->consumeFocusEvent(false);
5487}
5488
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005489/**
5490 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5491 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5492 * of the 'slipperyEnterWindow'.
5493 *
5494 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5495 * a way so that the touched location is no longer covered by the top window.
5496 *
5497 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5498 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5499 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5500 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5501 * with ACTION_DOWN).
5502 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5503 * window moved itself away from the touched location and had Flag::SLIPPERY.
5504 *
5505 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5506 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5507 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5508 *
5509 * In this test, we ensure that the event received by the bottom window has
5510 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5511 */
5512TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00005513 constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
5514 constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005515
5516 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5517 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5518
5519 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005520 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005521 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005522 // Make sure this one overlaps the bottom window
5523 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5524 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5525 // one. Windows with the same owner are not considered to be occluding each other.
5526 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5527
5528 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005529 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005530 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5531
5532 mDispatcher->setInputWindows(
5533 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5534
5535 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005536 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5537 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5538 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005539 slipperyExitWindow->consumeMotionDown();
5540 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5541 mDispatcher->setInputWindows(
5542 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5543
Prabir Pradhan678438e2023-04-13 19:32:51 +00005544 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5545 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5546 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005547
5548 slipperyExitWindow->consumeMotionCancel();
5549
5550 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5551 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5552}
5553
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005554/**
5555 * Two windows, one on the left and another on the right. The left window is slippery. The right
5556 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5557 * touch moves from the left window into the right window, the gesture should continue to go to the
5558 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5559 * reproduces a crash.
5560 */
5561TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5562 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5563
5564 sp<FakeWindowHandle> leftSlipperyWindow =
5565 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5566 leftSlipperyWindow->setSlippery(true);
5567 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5568
5569 sp<FakeWindowHandle> rightDropTouchesWindow =
5570 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5571 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5572 rightDropTouchesWindow->setDropInput(true);
5573
5574 mDispatcher->setInputWindows(
5575 {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}});
5576
5577 // Start touch in the left window
5578 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5579 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5580 .build());
5581 leftSlipperyWindow->consumeMotionDown();
5582
5583 // And move it into the right window
5584 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5585 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5586 .build());
5587
5588 // Since the right window isn't eligible to receive input, touch does not slip.
5589 // The left window continues to receive the gesture.
5590 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5591 rightDropTouchesWindow->assertNoEvents();
5592}
5593
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005594TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
5595 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5596
5597 sp<FakeWindowHandle> leftWindow =
5598 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5599 leftWindow->setFrame(Rect(0, 0, 100, 100));
5600 leftWindow->setOwnerInfo(1, 101);
5601
5602 sp<FakeWindowHandle> rightSpy =
5603 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
5604 rightSpy->setFrame(Rect(100, 0, 200, 100));
5605 rightSpy->setOwnerInfo(2, 102);
5606 rightSpy->setSpy(true);
5607 rightSpy->setTrustedOverlay(true);
5608
5609 sp<FakeWindowHandle> rightWindow =
5610 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5611 rightWindow->setFrame(Rect(100, 0, 200, 100));
5612 rightWindow->setOwnerInfo(3, 103);
5613
5614 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightSpy, rightWindow, leftWindow}}});
5615
5616 // Touch in the left window
5617 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5618 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5619 .build());
5620 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
5621 mDispatcher->waitForIdle();
5622 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {101}));
5623
5624 // Touch another finger over the right windows
5625 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5626 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5627 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5628 .build());
5629 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
5630 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
5631 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
5632 mDispatcher->waitForIdle();
5633 ASSERT_NO_FATAL_FAILURE(
5634 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {101, 102, 103}));
5635
5636 // Release finger over left window. The UP actions are not treated as device interaction.
5637 // The windows that did not receive the UP pointer will receive MOVE events, but since this
5638 // is part of the UP action, we do not treat this as device interaction.
5639 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
5640 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5641 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5642 .build());
5643 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
5644 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5645 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5646 mDispatcher->waitForIdle();
5647 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5648
5649 // Move remaining finger
5650 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5651 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5652 .build());
5653 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5654 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5655 mDispatcher->waitForIdle();
5656 ASSERT_NO_FATAL_FAILURE(
5657 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {102, 103}));
5658
5659 // Release all fingers
5660 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5661 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5662 .build());
5663 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
5664 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
5665 mDispatcher->waitForIdle();
5666 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5667}
5668
5669TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
5670 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5671
5672 sp<FakeWindowHandle> window =
5673 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5674 window->setFrame(Rect(0, 0, 100, 100));
5675 window->setOwnerInfo(1, 101);
5676
5677 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5678 setFocusedWindow(window);
5679 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
5680
5681 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
5682 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
5683 mDispatcher->waitForIdle();
5684 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {101}));
5685
5686 // The UP actions are not treated as device interaction.
5687 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
5688 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
5689 mDispatcher->waitForIdle();
5690 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5691}
5692
Garfield Tan1c7bc862020-01-28 13:24:04 -08005693class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5694protected:
5695 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5696 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5697
Chris Yea209fde2020-07-22 13:54:51 -07005698 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005699 sp<FakeWindowHandle> mWindow;
5700
5701 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005702 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005703 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Prabir Pradhana41d2442023-04-20 21:30:40 +00005704 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Prabir Pradhan87112a72023-04-20 19:13:39 +00005705 mDispatcher->requestRefreshConfiguration();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005706 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
5707 ASSERT_EQ(OK, mDispatcher->start());
5708
5709 setUpWindow();
5710 }
5711
5712 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005713 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005714 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005715
Vishnu Nair47074b82020-08-14 11:54:47 -07005716 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005717 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005718 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005719 mWindow->consumeFocusEvent(true);
5720 }
5721
Chris Ye2ad95392020-09-01 13:44:44 -07005722 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005723 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005724 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005725 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005726 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005727
5728 // Window should receive key down event.
5729 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5730 }
5731
5732 void expectKeyRepeatOnce(int32_t repeatCount) {
5733 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5734 InputEvent* repeatEvent = mWindow->consume();
5735 ASSERT_NE(nullptr, repeatEvent);
5736
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005737 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005738
5739 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5740 uint32_t eventAction = repeatKeyEvent->getAction();
5741 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5742 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5743 }
5744
Chris Ye2ad95392020-09-01 13:44:44 -07005745 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005746 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005747 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005748 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005749 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005750
5751 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005752 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005753 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005754 }
5755};
5756
5757TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005758 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005759 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5760 expectKeyRepeatOnce(repeatCount);
5761 }
5762}
5763
5764TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005765 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005766 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5767 expectKeyRepeatOnce(repeatCount);
5768 }
Harry Cutts33476232023-01-30 19:57:29 +00005769 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005770 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005771 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5772 expectKeyRepeatOnce(repeatCount);
5773 }
5774}
5775
5776TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005777 sendAndConsumeKeyDown(/*deviceId=*/1);
5778 expectKeyRepeatOnce(/*repeatCount=*/1);
5779 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005780 mWindow->assertNoEvents();
5781}
5782
5783TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005784 sendAndConsumeKeyDown(/*deviceId=*/1);
5785 expectKeyRepeatOnce(/*repeatCount=*/1);
5786 sendAndConsumeKeyDown(/*deviceId=*/2);
5787 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005788 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005789 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005790 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005791 expectKeyRepeatOnce(/*repeatCount=*/2);
5792 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005793 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005794 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005795 mWindow->assertNoEvents();
5796}
5797
5798TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005799 sendAndConsumeKeyDown(/*deviceId=*/1);
5800 expectKeyRepeatOnce(/*repeatCount=*/1);
5801 sendAndConsumeKeyDown(/*deviceId=*/2);
5802 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005803 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005804 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005805 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005806 mWindow->assertNoEvents();
5807}
5808
liushenxiang42232912021-05-21 20:24:09 +08005809TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5810 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005811 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005812 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005813 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5814 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5815 mWindow->assertNoEvents();
5816}
5817
Garfield Tan1c7bc862020-01-28 13:24:04 -08005818TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005819 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005820 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005821 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5822 InputEvent* repeatEvent = mWindow->consume();
5823 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5824 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5825 IdGenerator::getSource(repeatEvent->getId()));
5826 }
5827}
5828
5829TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005830 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005831 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005832
5833 std::unordered_set<int32_t> idSet;
5834 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5835 InputEvent* repeatEvent = mWindow->consume();
5836 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5837 int32_t id = repeatEvent->getId();
5838 EXPECT_EQ(idSet.end(), idSet.find(id));
5839 idSet.insert(id);
5840 }
5841}
5842
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005843/* Test InputDispatcher for MultiDisplay */
5844class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5845public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005846 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005847 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005848
Chris Yea209fde2020-07-22 13:54:51 -07005849 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005850 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005851 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005852
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005853 // Set focus window for primary display, but focused display would be second one.
5854 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005855 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005856 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005857 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005858 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005859
Chris Yea209fde2020-07-22 13:54:51 -07005860 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005861 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005862 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005863 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005864 // Set focus display to second one.
5865 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5866 // Set focus window for second display.
5867 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005868 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005869 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005870 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005871 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005872 }
5873
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005874 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005875 InputDispatcherTest::TearDown();
5876
Chris Yea209fde2020-07-22 13:54:51 -07005877 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005878 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005879 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005880 windowInSecondary.clear();
5881 }
5882
5883protected:
Chris Yea209fde2020-07-22 13:54:51 -07005884 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005885 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005886 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005887 sp<FakeWindowHandle> windowInSecondary;
5888};
5889
5890TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5891 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5893 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5894 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005895 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005896 windowInSecondary->assertNoEvents();
5897
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005898 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005899 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5900 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5901 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005902 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005903 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005904}
5905
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005906TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005907 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5909 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005910 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005911 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005912 windowInSecondary->assertNoEvents();
5913
5914 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005915 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005916 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005917 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005918 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005919
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005920 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005921 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005922
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005923 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005924 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005925 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005926
5927 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005928 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005929 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005930 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005931 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005932 windowInSecondary->assertNoEvents();
5933}
5934
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005935// Test per-display input monitors for motion event.
5936TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005937 FakeMonitorReceiver monitorInPrimary =
5938 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5939 FakeMonitorReceiver monitorInSecondary =
5940 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005941
5942 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5944 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5945 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005946 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005947 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005948 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005949 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005950
5951 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005952 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5953 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5954 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005955 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005956 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005957 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005958 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005959
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005960 // Lift up the touch from the second display
5961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5962 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5963 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5964 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5965 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5966
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005967 // Test inject a non-pointer motion event.
5968 // If specific a display, it will dispatch to the focused window of particular display,
5969 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005970 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5971 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5972 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005973 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005974 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005975 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005976 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005977}
5978
5979// Test per-display input monitors for key event.
5980TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005981 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005982 FakeMonitorReceiver monitorInPrimary =
5983 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5984 FakeMonitorReceiver monitorInSecondary =
5985 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005986
5987 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5989 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005990 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005991 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005992 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005993 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005994}
5995
Vishnu Nair958da932020-08-21 17:12:37 -07005996TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
5997 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005998 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005999 secondWindowInPrimary->setFocusable(true);
6000 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
6001 setFocusedWindow(secondWindowInPrimary);
6002 windowInPrimary->consumeFocusEvent(false);
6003 secondWindowInPrimary->consumeFocusEvent(true);
6004
6005 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006006 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
6007 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006008 windowInPrimary->assertNoEvents();
6009 windowInSecondary->assertNoEvents();
6010 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6011}
6012
Arthur Hungdfd528e2021-12-08 13:23:04 +00006013TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6014 FakeMonitorReceiver monitorInPrimary =
6015 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6016 FakeMonitorReceiver monitorInSecondary =
6017 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6018
6019 // Test touch down on primary display.
6020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6021 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6022 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6023 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6024 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6025
6026 // Test touch down on second display.
6027 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6028 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
6029 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6030 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6031 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6032
6033 // Trigger cancel touch.
6034 mDispatcher->cancelCurrentTouch();
6035 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6036 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6037 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6038 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6039
6040 // Test inject a move motion event, no window/monitor should receive the event.
6041 ASSERT_EQ(InputEventInjectionResult::FAILED,
6042 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6043 ADISPLAY_ID_DEFAULT, {110, 200}))
6044 << "Inject motion event should return InputEventInjectionResult::FAILED";
6045 windowInPrimary->assertNoEvents();
6046 monitorInPrimary.assertNoEvents();
6047
6048 ASSERT_EQ(InputEventInjectionResult::FAILED,
6049 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6050 SECOND_DISPLAY_ID, {110, 200}))
6051 << "Inject motion event should return InputEventInjectionResult::FAILED";
6052 windowInSecondary->assertNoEvents();
6053 monitorInSecondary.assertNoEvents();
6054}
6055
Jackal Guof9696682018-10-05 12:23:23 +08006056class InputFilterTest : public InputDispatcherTest {
6057protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006058 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6059 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006060 NotifyMotionArgs motionArgs;
6061
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006062 motionArgs =
6063 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006064 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006065 motionArgs =
6066 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006067 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006068 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006069 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006070 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006071 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006072 } else {
6073 mFakePolicy->assertFilterInputEventWasNotCalled();
6074 }
6075 }
6076
6077 void testNotifyKey(bool expectToBeFiltered) {
6078 NotifyKeyArgs keyArgs;
6079
6080 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006081 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006082 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006083 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006084 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006085
6086 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006087 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006088 } else {
6089 mFakePolicy->assertFilterInputEventWasNotCalled();
6090 }
6091 }
6092};
6093
6094// Test InputFilter for MotionEvent
6095TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6096 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
6097 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
6098 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
6099
6100 // Enable InputFilter
6101 mDispatcher->setInputFilterEnabled(true);
6102 // Test touch on both primary and second display, and check if both events are filtered.
6103 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
6104 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
6105
6106 // Disable InputFilter
6107 mDispatcher->setInputFilterEnabled(false);
6108 // Test touch on both primary and second display, and check if both events aren't filtered.
6109 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
6110 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
6111}
6112
6113// Test InputFilter for KeyEvent
6114TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6115 // Since the InputFilter is disabled by default, check if key event aren't filtered.
6116 testNotifyKey(/*expectToBeFiltered*/ false);
6117
6118 // Enable InputFilter
6119 mDispatcher->setInputFilterEnabled(true);
6120 // Send a key event, and check if it is filtered.
6121 testNotifyKey(/*expectToBeFiltered*/ true);
6122
6123 // Disable InputFilter
6124 mDispatcher->setInputFilterEnabled(false);
6125 // Send a key event, and check if it isn't filtered.
6126 testNotifyKey(/*expectToBeFiltered*/ false);
6127}
6128
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006129// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6130// logical display coordinate space.
6131TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6132 ui::Transform firstDisplayTransform;
6133 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6134 ui::Transform secondDisplayTransform;
6135 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6136
6137 std::vector<gui::DisplayInfo> displayInfos(2);
6138 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6139 displayInfos[0].transform = firstDisplayTransform;
6140 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6141 displayInfos[1].transform = secondDisplayTransform;
6142
Patrick Williamsd828f302023-04-28 17:52:08 -05006143 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006144
6145 // Enable InputFilter
6146 mDispatcher->setInputFilterEnabled(true);
6147
6148 // Ensure the correct transforms are used for the displays.
6149 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
6150 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
6151}
6152
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006153class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6154protected:
6155 virtual void SetUp() override {
6156 InputDispatcherTest::SetUp();
6157
6158 /**
6159 * We don't need to enable input filter to test the injected event policy, but we enabled it
6160 * here to make the tests more realistic, since this policy only matters when inputfilter is
6161 * on.
6162 */
6163 mDispatcher->setInputFilterEnabled(true);
6164
6165 std::shared_ptr<InputApplicationHandle> application =
6166 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006167 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6168 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006169
6170 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6171 mWindow->setFocusable(true);
6172 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6173 setFocusedWindow(mWindow);
6174 mWindow->consumeFocusEvent(true);
6175 }
6176
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006177 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6178 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006179 KeyEvent event;
6180
6181 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6182 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6183 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006184 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006185 const int32_t additionalPolicyFlags =
6186 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6187 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006188 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006189 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6190 policyFlags | additionalPolicyFlags));
6191
6192 InputEvent* received = mWindow->consume();
6193 ASSERT_NE(nullptr, received);
6194 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006195 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006196 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
6197 ASSERT_EQ(flags, keyEvent.getFlags());
6198 }
6199
6200 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6201 int32_t flags) {
6202 MotionEvent event;
6203 PointerProperties pointerProperties[1];
6204 PointerCoords pointerCoords[1];
6205 pointerProperties[0].clear();
6206 pointerProperties[0].id = 0;
6207 pointerCoords[0].clear();
6208 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6209 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6210
6211 ui::Transform identityTransform;
6212 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6213 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6214 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6215 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6216 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006217 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006218 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006219 /*pointerCount*/ 1, pointerProperties, pointerCoords);
6220
6221 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006223 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006224 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6225 policyFlags | additionalPolicyFlags));
6226
6227 InputEvent* received = mWindow->consume();
6228 ASSERT_NE(nullptr, received);
6229 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006230 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006231 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
6232 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006233 }
6234
6235private:
6236 sp<FakeWindowHandle> mWindow;
6237};
6238
6239TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006240 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6241 // filter. Without it, the event will no different from a regularly injected event, and the
6242 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006243 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6244 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006245}
6246
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006247TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006248 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006249 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006250 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6251}
6252
6253TEST_F(InputFilterInjectionPolicyTest,
6254 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6255 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006256 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006257 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006258}
6259
6260TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006261 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6262 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006263}
6264
chaviwfd6d3512019-03-25 13:23:49 -07006265class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006266 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006267 InputDispatcherTest::SetUp();
6268
Chris Yea209fde2020-07-22 13:54:51 -07006269 std::shared_ptr<FakeApplicationHandle> application =
6270 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006271 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006272 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006273 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006274
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006275 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006276 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006277 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006278
6279 // Set focused application.
6280 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006281 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006282
6283 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00006284 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006285 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006286 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006287 }
6288
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006289 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006290 InputDispatcherTest::TearDown();
6291
6292 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006293 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006294 }
6295
6296protected:
6297 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006298 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006299 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006300};
6301
6302// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6303// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6304// the onPointerDownOutsideFocus callback.
6305TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006307 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6308 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006309 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006310 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006311
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006312 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006313 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6314}
6315
6316// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6317// DOWN on the window that doesn't have focus. Ensure no window received the
6318// onPointerDownOutsideFocus callback.
6319TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006320 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006321 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006322 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006323 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006324
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006325 ASSERT_TRUE(mDispatcher->waitForIdle());
6326 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006327}
6328
6329// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6330// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6331TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006332 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6333 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006334 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006335 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006336
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006337 ASSERT_TRUE(mDispatcher->waitForIdle());
6338 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006339}
6340
6341// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6342// DOWN on the window that already has focus. Ensure no window received the
6343// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006344TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006346 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006347 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006348 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006349 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006350
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006351 ASSERT_TRUE(mDispatcher->waitForIdle());
6352 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006353}
6354
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006355// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6356// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6357TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6358 const MotionEvent event =
6359 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6360 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006361 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006362 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6363 .build();
6364 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6365 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6366 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6367
6368 ASSERT_TRUE(mDispatcher->waitForIdle());
6369 mFakePolicy->assertOnPointerDownWasNotCalled();
6370 // Ensure that the unfocused window did not receive any FOCUS events.
6371 mUnfocusedWindow->assertNoEvents();
6372}
6373
chaviwaf87b3e2019-10-01 16:59:28 -07006374// These tests ensures we can send touch events to a single client when there are multiple input
6375// windows that point to the same client token.
6376class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6377 virtual void SetUp() override {
6378 InputDispatcherTest::SetUp();
6379
Chris Yea209fde2020-07-22 13:54:51 -07006380 std::shared_ptr<FakeApplicationHandle> application =
6381 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006382 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6383 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006384 mWindow1->setFrame(Rect(0, 0, 100, 100));
6385
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006386 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6387 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006388 mWindow2->setFrame(Rect(100, 100, 200, 200));
6389
Arthur Hung72d8dc32020-03-28 00:48:39 +00006390 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006391 }
6392
6393protected:
6394 sp<FakeWindowHandle> mWindow1;
6395 sp<FakeWindowHandle> mWindow2;
6396
6397 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006398 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006399 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6400 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006401 }
6402
6403 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6404 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006405 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006406 InputEvent* event = window->consume();
6407
6408 ASSERT_NE(nullptr, event) << name.c_str()
6409 << ": consumer should have returned non-NULL event.";
6410
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006411 ASSERT_EQ(InputEventType::MOTION, event->getType())
6412 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006413
6414 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006415 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006416 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006417
6418 for (size_t i = 0; i < points.size(); i++) {
6419 float expectedX = points[i].x;
6420 float expectedY = points[i].y;
6421
6422 EXPECT_EQ(expectedX, motionEvent.getX(i))
6423 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6424 << ", got " << motionEvent.getX(i);
6425 EXPECT_EQ(expectedY, motionEvent.getY(i))
6426 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6427 << ", got " << motionEvent.getY(i);
6428 }
6429 }
chaviw9eaa22c2020-07-01 16:21:27 -07006430
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006431 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006432 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006433 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6434 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006435
6436 // Always consume from window1 since it's the window that has the InputReceiver
6437 consumeMotionEvent(mWindow1, action, expectedPoints);
6438 }
chaviwaf87b3e2019-10-01 16:59:28 -07006439};
6440
6441TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6442 // Touch Window 1
6443 PointF touchedPoint = {10, 10};
6444 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006445 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006446
6447 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006448 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006449
6450 // Touch Window 2
6451 touchedPoint = {150, 150};
6452 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006453 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006454}
6455
chaviw9eaa22c2020-07-01 16:21:27 -07006456TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6457 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006458 mWindow2->setWindowScale(0.5f, 0.5f);
6459
6460 // Touch Window 1
6461 PointF touchedPoint = {10, 10};
6462 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006463 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006464 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006465 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006466
6467 // Touch Window 2
6468 touchedPoint = {150, 150};
6469 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006470 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6471 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006472
chaviw9eaa22c2020-07-01 16:21:27 -07006473 // Update the transform so rotation is set
6474 mWindow2->setWindowTransform(0, -1, 1, 0);
6475 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6476 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006477}
6478
chaviw9eaa22c2020-07-01 16:21:27 -07006479TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006480 mWindow2->setWindowScale(0.5f, 0.5f);
6481
6482 // Touch Window 1
6483 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6484 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006485 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006486
6487 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006488 touchedPoints.push_back(PointF{150, 150});
6489 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006490 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006491
chaviw9eaa22c2020-07-01 16:21:27 -07006492 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006493 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006494 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006495
chaviw9eaa22c2020-07-01 16:21:27 -07006496 // Update the transform so rotation is set for Window 2
6497 mWindow2->setWindowTransform(0, -1, 1, 0);
6498 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006499 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006500}
6501
chaviw9eaa22c2020-07-01 16:21:27 -07006502TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006503 mWindow2->setWindowScale(0.5f, 0.5f);
6504
6505 // Touch Window 1
6506 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6507 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006508 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006509
6510 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006511 touchedPoints.push_back(PointF{150, 150});
6512 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006513
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006514 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006515
6516 // Move both windows
6517 touchedPoints = {{20, 20}, {175, 175}};
6518 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6519 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6520
chaviw9eaa22c2020-07-01 16:21:27 -07006521 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006522
chaviw9eaa22c2020-07-01 16:21:27 -07006523 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006524 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006525 expectedPoints.pop_back();
6526
6527 // Touch Window 2
6528 mWindow2->setWindowTransform(0, -1, 1, 0);
6529 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006530 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006531
6532 // Move both windows
6533 touchedPoints = {{20, 20}, {175, 175}};
6534 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6535 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6536
6537 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006538}
6539
6540TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6541 mWindow1->setWindowScale(0.5f, 0.5f);
6542
6543 // Touch Window 1
6544 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6545 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006546 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006547
6548 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006549 touchedPoints.push_back(PointF{150, 150});
6550 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006551
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006552 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006553
6554 // Move both windows
6555 touchedPoints = {{20, 20}, {175, 175}};
6556 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6557 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6558
chaviw9eaa22c2020-07-01 16:21:27 -07006559 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006560}
6561
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006562/**
6563 * When one of the windows is slippery, the touch should not slip into the other window with the
6564 * same input channel.
6565 */
6566TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6567 mWindow1->setSlippery(true);
6568 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6569
6570 // Touch down in window 1
6571 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6572 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6573 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6574
6575 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6576 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6577 // getting generated.
6578 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6579 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6580
6581 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6582}
6583
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006584/**
6585 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
6586 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
6587 * that the pointer is hovering over may have a different transform.
6588 */
6589TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
6590 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6591
6592 // Start hover in window 1
6593 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
6594 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6595 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6596 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
6597
6598 // Move hover to window 2.
6599 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6600 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6601
6602 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
6603 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6604 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
6605}
6606
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006607class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6608 virtual void SetUp() override {
6609 InputDispatcherTest::SetUp();
6610
Chris Yea209fde2020-07-22 13:54:51 -07006611 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006612 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006613 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6614 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006615 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006616 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006617 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006618
6619 // Set focused application.
6620 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6621
6622 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006623 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006624 mWindow->consumeFocusEvent(true);
6625 }
6626
6627 virtual void TearDown() override {
6628 InputDispatcherTest::TearDown();
6629 mWindow.clear();
6630 }
6631
6632protected:
Chris Yea209fde2020-07-22 13:54:51 -07006633 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006634 sp<FakeWindowHandle> mWindow;
6635 static constexpr PointF WINDOW_LOCATION = {20, 20};
6636
6637 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006638 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006639 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6640 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006642 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6643 WINDOW_LOCATION));
6644 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006645
6646 sp<FakeWindowHandle> addSpyWindow() {
6647 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006648 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006649 spy->setTrustedOverlay(true);
6650 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006651 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006652 spy->setDispatchingTimeout(30ms);
6653 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6654 return spy;
6655 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006656};
6657
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006658// Send a tap and respond, which should not cause an ANR.
6659TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6660 tapOnWindow();
6661 mWindow->consumeMotionDown();
6662 mWindow->consumeMotionUp();
6663 ASSERT_TRUE(mDispatcher->waitForIdle());
6664 mFakePolicy->assertNotifyAnrWasNotCalled();
6665}
6666
6667// Send a regular key and respond, which should not cause an ANR.
6668TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006670 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6671 ASSERT_TRUE(mDispatcher->waitForIdle());
6672 mFakePolicy->assertNotifyAnrWasNotCalled();
6673}
6674
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006675TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6676 mWindow->setFocusable(false);
6677 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6678 mWindow->consumeFocusEvent(false);
6679
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006680 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006681 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6682 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6683 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006684 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006685 // Key will not go to window because we have no focused window.
6686 // The 'no focused window' ANR timer should start instead.
6687
6688 // Now, the focused application goes away.
6689 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6690 // The key should get dropped and there should be no ANR.
6691
6692 ASSERT_TRUE(mDispatcher->waitForIdle());
6693 mFakePolicy->assertNotifyAnrWasNotCalled();
6694}
6695
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006696// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006697// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6698// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006699TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006701 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6702 WINDOW_LOCATION));
6703
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006704 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6705 ASSERT_TRUE(sequenceNum);
6706 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006707 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006708
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006709 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006710 mWindow->consumeMotionEvent(
6711 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006712 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006713 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006714}
6715
6716// Send a key to the app and have the app not respond right away.
6717TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6718 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006720 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6721 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006722 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006723 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006724 ASSERT_TRUE(mDispatcher->waitForIdle());
6725}
6726
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006727// We have a focused application, but no focused window
6728TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006729 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006730 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6731 mWindow->consumeFocusEvent(false);
6732
6733 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006734 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006735 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6736 WINDOW_LOCATION));
6737 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6738 mDispatcher->waitForIdle();
6739 mFakePolicy->assertNotifyAnrWasNotCalled();
6740
6741 // Once a focused event arrives, we get an ANR for this application
6742 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6743 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006744 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006745 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6746 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006747 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006748 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006749 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006750 ASSERT_TRUE(mDispatcher->waitForIdle());
6751}
6752
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006753/**
6754 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6755 * there will not be an ANR.
6756 */
6757TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6758 mWindow->setFocusable(false);
6759 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6760 mWindow->consumeFocusEvent(false);
6761
6762 KeyEvent event;
6763 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6764 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6765
6766 // Define a valid key down event that is stale (too old).
6767 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6768 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006769 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006770
6771 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6772
6773 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006774 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006775 InputEventInjectionSync::WAIT_FOR_RESULT,
6776 INJECT_EVENT_TIMEOUT, policyFlags);
6777 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6778 << "Injection should fail because the event is stale";
6779
6780 ASSERT_TRUE(mDispatcher->waitForIdle());
6781 mFakePolicy->assertNotifyAnrWasNotCalled();
6782 mWindow->assertNoEvents();
6783}
6784
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006785// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006786// Make sure that we don't notify policy twice about the same ANR.
6787TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006788 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006789 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6790 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006791
6792 // Once a focused event arrives, we get an ANR for this application
6793 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6794 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006795 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006796 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6797 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006798 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006799 const std::chrono::duration appTimeout =
6800 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6801 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006802
Vishnu Naire4df8752022-09-08 09:17:55 -07006803 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006804 // ANR should not be raised again. It is up to policy to do that if it desires.
6805 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006806
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006807 // If we now get a focused window, the ANR should stop, but the policy handles that via
6808 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006809 ASSERT_TRUE(mDispatcher->waitForIdle());
6810}
6811
6812// We have a focused application, but no focused window
6813TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006814 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006815 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6816 mWindow->consumeFocusEvent(false);
6817
6818 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006819 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006820 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006821 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6822 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006823
Vishnu Naire4df8752022-09-08 09:17:55 -07006824 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6825 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006826
6827 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006828 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006829 ASSERT_TRUE(mDispatcher->waitForIdle());
6830 mWindow->assertNoEvents();
6831}
6832
6833/**
6834 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6835 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6836 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6837 * the ANR mechanism should still work.
6838 *
6839 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6840 * DOWN event, while not responding on the second one.
6841 */
6842TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6843 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6844 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6845 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6846 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6847 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006848 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006849
6850 // Now send ACTION_UP, with identical timestamp
6851 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6852 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6853 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6854 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006855 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006856
6857 // We have now sent down and up. Let's consume first event and then ANR on the second.
6858 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6859 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006860 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006861}
6862
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006863// A spy window can receive an ANR
6864TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6865 sp<FakeWindowHandle> spy = addSpyWindow();
6866
6867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6868 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6869 WINDOW_LOCATION));
6870 mWindow->consumeMotionDown();
6871
6872 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6873 ASSERT_TRUE(sequenceNum);
6874 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006875 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006876
6877 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006878 spy->consumeMotionEvent(
6879 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006880 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006881 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006882}
6883
6884// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006885// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006886TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6887 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006888
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6890 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006891 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006893
6894 // Stuck on the ACTION_UP
6895 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006896 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006897
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006898 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006899 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006900 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6901 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006902
6903 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6904 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006905 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006906 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006907 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006908}
6909
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006910// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006911// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006912TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6913 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006914
6915 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006916 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6917 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006918
6919 mWindow->consumeMotionDown();
6920 // Stuck on the ACTION_UP
6921 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006922 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006923
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006924 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006925 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006926 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6927 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006928
6929 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6930 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006931 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006932 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006933 spy->assertNoEvents();
6934}
6935
6936TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6937 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6938
6939 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6940
6941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6942 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6943 WINDOW_LOCATION));
6944
6945 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6946 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6947 ASSERT_TRUE(consumeSeq);
6948
Prabir Pradhanedd96402022-02-15 01:46:16 -08006949 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006950
6951 monitor.finishEvent(*consumeSeq);
6952 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6953
6954 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006955 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006956}
6957
6958// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6959// process events, you don't get an anr. When the window later becomes unresponsive again, you
6960// get an ANR again.
6961// 1. tap -> block on ACTION_UP -> receive ANR
6962// 2. consume all pending events (= queue becomes healthy again)
6963// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6964TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6965 tapOnWindow();
6966
6967 mWindow->consumeMotionDown();
6968 // Block on ACTION_UP
6969 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006970 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006971 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6972 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006973 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006974 mWindow->assertNoEvents();
6975
6976 tapOnWindow();
6977 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006978 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006979 mWindow->consumeMotionUp();
6980
6981 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006982 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006983 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006984 mWindow->assertNoEvents();
6985}
6986
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006987// If a connection remains unresponsive for a while, make sure policy is only notified once about
6988// it.
6989TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006990 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006991 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6992 WINDOW_LOCATION));
6993
6994 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006995 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006996 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006997 // 'notifyConnectionUnresponsive' should only be called once per connection
6998 mFakePolicy->assertNotifyAnrWasNotCalled();
6999 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007000 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007001 mWindow->consumeMotionEvent(
7002 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007003 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007004 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007005 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007006 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007007}
7008
7009/**
7010 * If a window is processing a motion event, and then a key event comes in, the key event should
7011 * not to to the focused window until the motion is processed.
7012 *
7013 * Warning!!!
7014 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7015 * and the injection timeout that we specify when injecting the key.
7016 * We must have the injection timeout (10ms) be smaller than
7017 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7018 *
7019 * If that value changes, this test should also change.
7020 */
7021TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7022 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7023 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7024
7025 tapOnWindow();
7026 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7027 ASSERT_TRUE(downSequenceNum);
7028 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7029 ASSERT_TRUE(upSequenceNum);
7030 // Don't finish the events yet, and send a key
7031 // Injection will "succeed" because we will eventually give up and send the key to the focused
7032 // window even if motions are still being processed. But because the injection timeout is short,
7033 // we will receive INJECTION_TIMED_OUT as the result.
7034
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007035 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007036 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007037 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
7038 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007039 // Key will not be sent to the window, yet, because the window is still processing events
7040 // and the key remains pending, waiting for the touch events to be processed
7041 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7042 ASSERT_FALSE(keySequenceNum);
7043
7044 std::this_thread::sleep_for(500ms);
7045 // if we wait long enough though, dispatcher will give up, and still send the key
7046 // to the focused window, even though we have not yet finished the motion event
7047 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7048 mWindow->finishEvent(*downSequenceNum);
7049 mWindow->finishEvent(*upSequenceNum);
7050}
7051
7052/**
7053 * If a window is processing a motion event, and then a key event comes in, the key event should
7054 * not go to the focused window until the motion is processed.
7055 * If then a new motion comes in, then the pending key event should be going to the currently
7056 * focused window right away.
7057 */
7058TEST_F(InputDispatcherSingleWindowAnr,
7059 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7060 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7061 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7062
7063 tapOnWindow();
7064 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7065 ASSERT_TRUE(downSequenceNum);
7066 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7067 ASSERT_TRUE(upSequenceNum);
7068 // Don't finish the events yet, and send a key
7069 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007071 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7072 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007073 // At this point, key is still pending, and should not be sent to the application yet.
7074 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7075 ASSERT_FALSE(keySequenceNum);
7076
7077 // Now tap down again. It should cause the pending key to go to the focused window right away.
7078 tapOnWindow();
7079 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7080 // the other events yet. We can finish events in any order.
7081 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7082 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7083 mWindow->consumeMotionDown();
7084 mWindow->consumeMotionUp();
7085 mWindow->assertNoEvents();
7086}
7087
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007088/**
7089 * Send an event to the app and have the app not respond right away.
7090 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7091 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7092 * At some point, the window becomes responsive again.
7093 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7094 */
7095TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7096 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7097 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7098 .build());
7099
7100 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7101 ASSERT_TRUE(sequenceNum);
7102 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7103 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7104
7105 mWindow->finishEvent(*sequenceNum);
7106 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7107 ASSERT_TRUE(mDispatcher->waitForIdle());
7108 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7109
7110 // Now that the window is responsive, let's continue the gesture.
7111 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7112 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7113 .build());
7114
7115 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7116 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7117 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7118 .build());
7119
7120 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7121 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7122 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7123 .build());
7124 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7125 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7126 .build());
7127 // We already canceled this pointer, so the window shouldn't get any new events.
7128 mWindow->assertNoEvents();
7129
7130 // Start another one.
7131 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7132 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7133 .build());
7134 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7135}
7136
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007137class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7138 virtual void SetUp() override {
7139 InputDispatcherTest::SetUp();
7140
Chris Yea209fde2020-07-22 13:54:51 -07007141 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007142 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007143 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7144 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007145 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007146 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007147 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007148
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007149 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7150 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05007151 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007152 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007153
7154 // Set focused application.
7155 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007156 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007157
7158 // Expect one focus window exist in display.
7159 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007160 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007161 mFocusedWindow->consumeFocusEvent(true);
7162 }
7163
7164 virtual void TearDown() override {
7165 InputDispatcherTest::TearDown();
7166
7167 mUnfocusedWindow.clear();
7168 mFocusedWindow.clear();
7169 }
7170
7171protected:
Chris Yea209fde2020-07-22 13:54:51 -07007172 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007173 sp<FakeWindowHandle> mUnfocusedWindow;
7174 sp<FakeWindowHandle> mFocusedWindow;
7175 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7176 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7177 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7178
7179 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7180
7181 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7182
7183private:
7184 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007186 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7187 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007188 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007189 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7190 location));
7191 }
7192};
7193
7194// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7195// should be ANR'd first.
7196TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007198 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7199 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007200 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007201 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007202 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007203 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007204 // We consumed all events, so no ANR
7205 ASSERT_TRUE(mDispatcher->waitForIdle());
7206 mFakePolicy->assertNotifyAnrWasNotCalled();
7207
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007209 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7210 FOCUSED_WINDOW_LOCATION));
7211 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7212 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007213
7214 const std::chrono::duration timeout =
7215 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007216 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007217 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7218 // sequence to make it consistent
7219 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007220 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007221 mFocusedWindow->consumeMotionDown();
7222 // This cancel is generated because the connection was unresponsive
7223 mFocusedWindow->consumeMotionCancel();
7224 mFocusedWindow->assertNoEvents();
7225 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007226 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007227 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7228 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007229 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007230}
7231
7232// If we have 2 windows with identical timeouts that are both unresponsive,
7233// it doesn't matter which order they should have ANR.
7234// But we should receive ANR for both.
7235TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7236 // Set the timeout for unfocused window to match the focused window
7237 mUnfocusedWindow->setDispatchingTimeout(10ms);
7238 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7239
7240 tapOnFocusedWindow();
7241 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08007242 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
7243 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
7244 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007245
7246 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007247 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
7248 mFocusedWindow->getToken() == anrConnectionToken2);
7249 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
7250 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007251
7252 ASSERT_TRUE(mDispatcher->waitForIdle());
7253 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007254
7255 mFocusedWindow->consumeMotionDown();
7256 mFocusedWindow->consumeMotionUp();
7257 mUnfocusedWindow->consumeMotionOutside();
7258
Prabir Pradhanedd96402022-02-15 01:46:16 -08007259 sp<IBinder> responsiveToken1, responsiveToken2;
7260 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
7261 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007262
7263 // Both applications should be marked as responsive, in any order
7264 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
7265 mFocusedWindow->getToken() == responsiveToken2);
7266 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
7267 mUnfocusedWindow->getToken() == responsiveToken2);
7268 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007269}
7270
7271// If a window is already not responding, the second tap on the same window should be ignored.
7272// We should also log an error to account for the dropped event (not tested here).
7273// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7274TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7275 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007276 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007277 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007278 // Receive the events, but don't respond
7279 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7280 ASSERT_TRUE(downEventSequenceNum);
7281 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7282 ASSERT_TRUE(upEventSequenceNum);
7283 const std::chrono::duration timeout =
7284 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007285 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007286
7287 // Tap once again
7288 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007289 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007290 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7291 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007292 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007293 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7294 FOCUSED_WINDOW_LOCATION));
7295 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7296 // valid touch target
7297 mUnfocusedWindow->assertNoEvents();
7298
7299 // Consume the first tap
7300 mFocusedWindow->finishEvent(*downEventSequenceNum);
7301 mFocusedWindow->finishEvent(*upEventSequenceNum);
7302 ASSERT_TRUE(mDispatcher->waitForIdle());
7303 // The second tap did not go to the focused window
7304 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007305 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007306 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7307 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007308 mFakePolicy->assertNotifyAnrWasNotCalled();
7309}
7310
7311// If you tap outside of all windows, there will not be ANR
7312TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007313 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007314 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7315 LOCATION_OUTSIDE_ALL_WINDOWS));
7316 ASSERT_TRUE(mDispatcher->waitForIdle());
7317 mFakePolicy->assertNotifyAnrWasNotCalled();
7318}
7319
7320// Since the focused window is paused, tapping on it should not produce any events
7321TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7322 mFocusedWindow->setPaused(true);
7323 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7324
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007325 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007326 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7327 FOCUSED_WINDOW_LOCATION));
7328
7329 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7330 ASSERT_TRUE(mDispatcher->waitForIdle());
7331 // Should not ANR because the window is paused, and touches shouldn't go to it
7332 mFakePolicy->assertNotifyAnrWasNotCalled();
7333
7334 mFocusedWindow->assertNoEvents();
7335 mUnfocusedWindow->assertNoEvents();
7336}
7337
7338/**
7339 * If a window is processing a motion event, and then a key event comes in, the key event should
7340 * not to to the focused window until the motion is processed.
7341 * If a different window becomes focused at this time, the key should go to that window instead.
7342 *
7343 * Warning!!!
7344 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7345 * and the injection timeout that we specify when injecting the key.
7346 * We must have the injection timeout (10ms) be smaller than
7347 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7348 *
7349 * If that value changes, this test should also change.
7350 */
7351TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7352 // Set a long ANR timeout to prevent it from triggering
7353 mFocusedWindow->setDispatchingTimeout(2s);
7354 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7355
7356 tapOnUnfocusedWindow();
7357 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7358 ASSERT_TRUE(downSequenceNum);
7359 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7360 ASSERT_TRUE(upSequenceNum);
7361 // Don't finish the events yet, and send a key
7362 // Injection will succeed because we will eventually give up and send the key to the focused
7363 // window even if motions are still being processed.
7364
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007365 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007366 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7367 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007369 // Key will not be sent to the window, yet, because the window is still processing events
7370 // and the key remains pending, waiting for the touch events to be processed
7371 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7372 ASSERT_FALSE(keySequenceNum);
7373
7374 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007375 mFocusedWindow->setFocusable(false);
7376 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007377 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007378 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007379
7380 // Focus events should precede the key events
7381 mUnfocusedWindow->consumeFocusEvent(true);
7382 mFocusedWindow->consumeFocusEvent(false);
7383
7384 // Finish the tap events, which should unblock dispatcher
7385 mUnfocusedWindow->finishEvent(*downSequenceNum);
7386 mUnfocusedWindow->finishEvent(*upSequenceNum);
7387
7388 // Now that all queues are cleared and no backlog in the connections, the key event
7389 // can finally go to the newly focused "mUnfocusedWindow".
7390 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7391 mFocusedWindow->assertNoEvents();
7392 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007393 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007394}
7395
7396// When the touch stream is split across 2 windows, and one of them does not respond,
7397// then ANR should be raised and the touch should be canceled for the unresponsive window.
7398// The other window should not be affected by that.
7399TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7400 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007401 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7402 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7403 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007404 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007405 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007406
7407 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007408 mDispatcher->notifyMotion(
7409 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7410 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007411
7412 const std::chrono::duration timeout =
7413 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007414 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007415
7416 mUnfocusedWindow->consumeMotionDown();
7417 mFocusedWindow->consumeMotionDown();
7418 // Focused window may or may not receive ACTION_MOVE
7419 // But it should definitely receive ACTION_CANCEL due to the ANR
7420 InputEvent* event;
7421 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7422 ASSERT_TRUE(moveOrCancelSequenceNum);
7423 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7424 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007425 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007426 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7427 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7428 mFocusedWindow->consumeMotionCancel();
7429 } else {
7430 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7431 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007432 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007433 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7434 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007435
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007436 mUnfocusedWindow->assertNoEvents();
7437 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007438 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007439}
7440
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007441/**
7442 * If we have no focused window, and a key comes in, we start the ANR timer.
7443 * The focused application should add a focused window before the timer runs out to prevent ANR.
7444 *
7445 * If the user touches another application during this time, the key should be dropped.
7446 * Next, if a new focused window comes in, without toggling the focused application,
7447 * then no ANR should occur.
7448 *
7449 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7450 * but in some cases the policy may not update the focused application.
7451 */
7452TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7453 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7454 std::make_shared<FakeApplicationHandle>();
7455 focusedApplication->setDispatchingTimeout(60ms);
7456 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7457 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7458 mFocusedWindow->setFocusable(false);
7459
7460 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7461 mFocusedWindow->consumeFocusEvent(false);
7462
7463 // Send a key. The ANR timer should start because there is no focused window.
7464 // 'focusedApplication' will get blamed if this timer completes.
7465 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007466 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007467 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7468 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
7469 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007470 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007471
7472 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7473 // then the injected touches won't cause the focused event to get dropped.
7474 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7475 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7476 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7477 // For this test, it means that the key would get delivered to the window once it becomes
7478 // focused.
7479 std::this_thread::sleep_for(10ms);
7480
7481 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007482 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7483 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7484 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007485
7486 // We do not consume the motion right away, because that would require dispatcher to first
7487 // process (== drop) the key event, and by that time, ANR will be raised.
7488 // Set the focused window first.
7489 mFocusedWindow->setFocusable(true);
7490 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7491 setFocusedWindow(mFocusedWindow);
7492 mFocusedWindow->consumeFocusEvent(true);
7493 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7494 // to another application. This could be a bug / behaviour in the policy.
7495
7496 mUnfocusedWindow->consumeMotionDown();
7497
7498 ASSERT_TRUE(mDispatcher->waitForIdle());
7499 // Should not ANR because we actually have a focused window. It was just added too slowly.
7500 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7501}
7502
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007503// These tests ensure we cannot send touch events to a window that's positioned behind a window
7504// that has feature NO_INPUT_CHANNEL.
7505// Layout:
7506// Top (closest to user)
7507// mNoInputWindow (above all windows)
7508// mBottomWindow
7509// Bottom (furthest from user)
7510class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7511 virtual void SetUp() override {
7512 InputDispatcherTest::SetUp();
7513
7514 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007515 mNoInputWindow =
7516 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7517 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007518 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007519 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007520 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7521 // It's perfectly valid for this window to not have an associated input channel
7522
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007523 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7524 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007525 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7526
7527 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7528 }
7529
7530protected:
7531 std::shared_ptr<FakeApplicationHandle> mApplication;
7532 sp<FakeWindowHandle> mNoInputWindow;
7533 sp<FakeWindowHandle> mBottomWindow;
7534};
7535
7536TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7537 PointF touchedPoint = {10, 10};
7538
Prabir Pradhan678438e2023-04-13 19:32:51 +00007539 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7540 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7541 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007542
7543 mNoInputWindow->assertNoEvents();
7544 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7545 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7546 // and therefore should prevent mBottomWindow from receiving touches
7547 mBottomWindow->assertNoEvents();
7548}
7549
7550/**
7551 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7552 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7553 */
7554TEST_F(InputDispatcherMultiWindowOcclusionTests,
7555 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007556 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7557 "Window with input channel and NO_INPUT_CHANNEL",
7558 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007559
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007560 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007561 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7562 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7563
7564 PointF touchedPoint = {10, 10};
7565
Prabir Pradhan678438e2023-04-13 19:32:51 +00007566 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7567 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7568 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007569
7570 mNoInputWindow->assertNoEvents();
7571 mBottomWindow->assertNoEvents();
7572}
7573
Vishnu Nair958da932020-08-21 17:12:37 -07007574class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7575protected:
7576 std::shared_ptr<FakeApplicationHandle> mApp;
7577 sp<FakeWindowHandle> mWindow;
7578 sp<FakeWindowHandle> mMirror;
7579
7580 virtual void SetUp() override {
7581 InputDispatcherTest::SetUp();
7582 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007583 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7584 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7585 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007586 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7587 mWindow->setFocusable(true);
7588 mMirror->setFocusable(true);
7589 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7590 }
7591};
7592
7593TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7594 // Request focus on a mirrored window
7595 setFocusedWindow(mMirror);
7596
7597 // window gets focused
7598 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007599 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7600 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007601 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7602}
7603
7604// A focused & mirrored window remains focused only if the window and its mirror are both
7605// focusable.
7606TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7607 setFocusedWindow(mMirror);
7608
7609 // window gets focused
7610 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007611 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7612 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007613 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7615 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007616 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7617
7618 mMirror->setFocusable(false);
7619 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7620
7621 // window loses focus since one of the windows associated with the token in not focusable
7622 mWindow->consumeFocusEvent(false);
7623
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007624 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7625 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007626 mWindow->assertNoEvents();
7627}
7628
7629// A focused & mirrored window remains focused until the window and its mirror both become
7630// invisible.
7631TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7632 setFocusedWindow(mMirror);
7633
7634 // window gets focused
7635 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007636 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7637 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007638 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7640 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007641 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7642
7643 mMirror->setVisible(false);
7644 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7645
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7647 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007648 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007649 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7650 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007651 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7652
7653 mWindow->setVisible(false);
7654 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7655
7656 // window loses focus only after all windows associated with the token become invisible.
7657 mWindow->consumeFocusEvent(false);
7658
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007659 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7660 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007661 mWindow->assertNoEvents();
7662}
7663
7664// A focused & mirrored window remains focused until both windows are removed.
7665TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7666 setFocusedWindow(mMirror);
7667
7668 // window gets focused
7669 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007670 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7671 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007672 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7674 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007675 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7676
7677 // single window is removed but the window token remains focused
7678 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7679
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7681 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007682 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7684 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007685 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7686
7687 // Both windows are removed
7688 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7689 mWindow->consumeFocusEvent(false);
7690
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007691 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7692 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007693 mWindow->assertNoEvents();
7694}
7695
7696// Focus request can be pending until one window becomes visible.
7697TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7698 // Request focus on an invisible mirror.
7699 mWindow->setVisible(false);
7700 mMirror->setVisible(false);
7701 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7702 setFocusedWindow(mMirror);
7703
7704 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007706 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7707 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007708
7709 mMirror->setVisible(true);
7710 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7711
7712 // window gets focused
7713 mWindow->consumeFocusEvent(true);
7714 // window gets the pending key event
7715 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7716}
Prabir Pradhan99987712020-11-10 18:43:05 -08007717
7718class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7719protected:
7720 std::shared_ptr<FakeApplicationHandle> mApp;
7721 sp<FakeWindowHandle> mWindow;
7722 sp<FakeWindowHandle> mSecondWindow;
7723
7724 void SetUp() override {
7725 InputDispatcherTest::SetUp();
7726 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007727 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007728 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007729 mSecondWindow =
7730 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007731 mSecondWindow->setFocusable(true);
7732
7733 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7734 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7735
7736 setFocusedWindow(mWindow);
7737 mWindow->consumeFocusEvent(true);
7738 }
7739
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007740 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007741 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007742 }
7743
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007744 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7745 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007746 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007747 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7748 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007749 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007750 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007751 }
7752};
7753
7754TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7755 // Ensure that capture cannot be obtained for unfocused windows.
7756 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7757 mFakePolicy->assertSetPointerCaptureNotCalled();
7758 mSecondWindow->assertNoEvents();
7759
7760 // Ensure that capture can be enabled from the focus window.
7761 requestAndVerifyPointerCapture(mWindow, true);
7762
7763 // Ensure that capture cannot be disabled from a window that does not have capture.
7764 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7765 mFakePolicy->assertSetPointerCaptureNotCalled();
7766
7767 // Ensure that capture can be disabled from the window with capture.
7768 requestAndVerifyPointerCapture(mWindow, false);
7769}
7770
7771TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007772 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007773
7774 setFocusedWindow(mSecondWindow);
7775
7776 // Ensure that the capture disabled event was sent first.
7777 mWindow->consumeCaptureEvent(false);
7778 mWindow->consumeFocusEvent(false);
7779 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007780 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007781
7782 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007783 notifyPointerCaptureChanged({});
7784 notifyPointerCaptureChanged(request);
7785 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007786 mWindow->assertNoEvents();
7787 mSecondWindow->assertNoEvents();
7788 mFakePolicy->assertSetPointerCaptureNotCalled();
7789}
7790
7791TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007792 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007793
7794 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007795 notifyPointerCaptureChanged({});
7796 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007797
7798 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007799 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007800 mWindow->consumeCaptureEvent(false);
7801 mWindow->assertNoEvents();
7802}
7803
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007804TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7805 requestAndVerifyPointerCapture(mWindow, true);
7806
7807 // The first window loses focus.
7808 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007809 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007810 mWindow->consumeCaptureEvent(false);
7811
7812 // Request Pointer Capture from the second window before the notification from InputReader
7813 // arrives.
7814 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007815 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007816
7817 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007818 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007819
7820 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007821 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007822
7823 mSecondWindow->consumeFocusEvent(true);
7824 mSecondWindow->consumeCaptureEvent(true);
7825}
7826
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007827TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7828 // App repeatedly enables and disables capture.
7829 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7830 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7831 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7832 mFakePolicy->assertSetPointerCaptureCalled(false);
7833 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7834 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7835
7836 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7837 // first request is now stale, this should do nothing.
7838 notifyPointerCaptureChanged(firstRequest);
7839 mWindow->assertNoEvents();
7840
7841 // InputReader notifies that the second request was enabled.
7842 notifyPointerCaptureChanged(secondRequest);
7843 mWindow->consumeCaptureEvent(true);
7844}
7845
Prabir Pradhan7092e262022-05-03 16:51:09 +00007846TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7847 requestAndVerifyPointerCapture(mWindow, true);
7848
7849 // App toggles pointer capture off and on.
7850 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7851 mFakePolicy->assertSetPointerCaptureCalled(false);
7852
7853 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7854 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7855
7856 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7857 // preceding "disable" request.
7858 notifyPointerCaptureChanged(enableRequest);
7859
7860 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7861 // any notifications.
7862 mWindow->assertNoEvents();
7863}
7864
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007865class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7866protected:
7867 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007868
7869 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7870 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7871
7872 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7873 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7874
7875 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7876 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7877 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7878 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7879 MAXIMUM_OBSCURING_OPACITY);
7880
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007881 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007882 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007883 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007884
7885 sp<FakeWindowHandle> mTouchWindow;
7886
7887 virtual void SetUp() override {
7888 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007889 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007890 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7891 }
7892
7893 virtual void TearDown() override {
7894 InputDispatcherTest::TearDown();
7895 mTouchWindow.clear();
7896 }
7897
chaviw3277faf2021-05-19 16:45:23 -05007898 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
7899 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007900 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007901 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007902 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007903 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007904 return window;
7905 }
7906
7907 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
7908 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7909 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007910 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007911 // Generate an arbitrary PID based on the UID
7912 window->setOwnerInfo(1777 + (uid % 10000), uid);
7913 return window;
7914 }
7915
7916 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007917 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7918 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7919 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007920 }
7921};
7922
7923TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007924 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007925 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007926 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007927
7928 touch();
7929
7930 mTouchWindow->assertNoEvents();
7931}
7932
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007933TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007934 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7935 const sp<FakeWindowHandle>& w =
7936 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7937 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7938
7939 touch();
7940
7941 mTouchWindow->assertNoEvents();
7942}
7943
7944TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007945 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7946 const sp<FakeWindowHandle>& w =
7947 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7948 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7949
7950 touch();
7951
7952 w->assertNoEvents();
7953}
7954
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007955TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007956 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7957 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007958
7959 touch();
7960
7961 mTouchWindow->consumeAnyMotionDown();
7962}
7963
7964TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007965 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007966 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007967 w->setFrame(Rect(0, 0, 50, 50));
7968 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007969
7970 touch({PointF{100, 100}});
7971
7972 mTouchWindow->consumeAnyMotionDown();
7973}
7974
7975TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007976 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007977 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007978 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7979
7980 touch();
7981
7982 mTouchWindow->consumeAnyMotionDown();
7983}
7984
7985TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7986 const sp<FakeWindowHandle>& w =
7987 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7988 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007989
7990 touch();
7991
7992 mTouchWindow->consumeAnyMotionDown();
7993}
7994
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007995TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7996 const sp<FakeWindowHandle>& w =
7997 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7998 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7999
8000 touch();
8001
8002 w->assertNoEvents();
8003}
8004
8005/**
8006 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8007 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8008 * window, the occluding window will still receive ACTION_OUTSIDE event.
8009 */
8010TEST_F(InputDispatcherUntrustedTouchesTest,
8011 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8012 const sp<FakeWindowHandle>& w =
8013 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008014 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008015 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8016
8017 touch();
8018
8019 w->consumeMotionOutside();
8020}
8021
8022TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8023 const sp<FakeWindowHandle>& w =
8024 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008025 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008026 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8027
8028 touch();
8029
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008030 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008031}
8032
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008033TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008034 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008035 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8036 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008037 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8038
8039 touch();
8040
8041 mTouchWindow->consumeAnyMotionDown();
8042}
8043
8044TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8045 const sp<FakeWindowHandle>& w =
8046 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8047 MAXIMUM_OBSCURING_OPACITY);
8048 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008049
8050 touch();
8051
8052 mTouchWindow->consumeAnyMotionDown();
8053}
8054
8055TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008056 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008057 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8058 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008059 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8060
8061 touch();
8062
8063 mTouchWindow->assertNoEvents();
8064}
8065
8066TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8067 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8068 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008069 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8070 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008071 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008072 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8073 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008074 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8075
8076 touch();
8077
8078 mTouchWindow->assertNoEvents();
8079}
8080
8081TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8082 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8083 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008084 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8085 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008086 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008087 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8088 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008089 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8090
8091 touch();
8092
8093 mTouchWindow->consumeAnyMotionDown();
8094}
8095
8096TEST_F(InputDispatcherUntrustedTouchesTest,
8097 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8098 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008099 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8100 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008101 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008102 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8103 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008104 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8105
8106 touch();
8107
8108 mTouchWindow->consumeAnyMotionDown();
8109}
8110
8111TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8112 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008113 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8114 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008115 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008116 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8117 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008118 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008119
8120 touch();
8121
8122 mTouchWindow->assertNoEvents();
8123}
8124
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008125TEST_F(InputDispatcherUntrustedTouchesTest,
8126 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8127 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008128 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8129 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008130 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008131 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8132 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008133 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8134
8135 touch();
8136
8137 mTouchWindow->assertNoEvents();
8138}
8139
8140TEST_F(InputDispatcherUntrustedTouchesTest,
8141 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8142 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008143 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8144 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008145 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008146 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8147 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008148 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8149
8150 touch();
8151
8152 mTouchWindow->consumeAnyMotionDown();
8153}
8154
8155TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8156 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008157 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8158 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008159 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8160
8161 touch();
8162
8163 mTouchWindow->consumeAnyMotionDown();
8164}
8165
8166TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8167 const sp<FakeWindowHandle>& w =
8168 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
8169 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8170
8171 touch();
8172
8173 mTouchWindow->consumeAnyMotionDown();
8174}
8175
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008176TEST_F(InputDispatcherUntrustedTouchesTest,
8177 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8178 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8179 const sp<FakeWindowHandle>& w =
8180 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
8181 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8182
8183 touch();
8184
8185 mTouchWindow->assertNoEvents();
8186}
8187
8188TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8189 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8190 const sp<FakeWindowHandle>& w =
8191 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
8192 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8193
8194 touch();
8195
8196 mTouchWindow->consumeAnyMotionDown();
8197}
8198
8199TEST_F(InputDispatcherUntrustedTouchesTest,
8200 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8201 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8202 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008203 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8204 OPACITY_ABOVE_THRESHOLD);
8205 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8206
8207 touch();
8208
8209 mTouchWindow->consumeAnyMotionDown();
8210}
8211
8212TEST_F(InputDispatcherUntrustedTouchesTest,
8213 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8214 const sp<FakeWindowHandle>& w1 =
8215 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8216 OPACITY_BELOW_THRESHOLD);
8217 const sp<FakeWindowHandle>& w2 =
8218 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8219 OPACITY_BELOW_THRESHOLD);
8220 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8221
8222 touch();
8223
8224 mTouchWindow->assertNoEvents();
8225}
8226
8227/**
8228 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8229 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8230 * (which alone would result in allowing touches) does not affect the blocking behavior.
8231 */
8232TEST_F(InputDispatcherUntrustedTouchesTest,
8233 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8234 const sp<FakeWindowHandle>& wB =
8235 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8236 OPACITY_BELOW_THRESHOLD);
8237 const sp<FakeWindowHandle>& wC =
8238 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8239 OPACITY_BELOW_THRESHOLD);
8240 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8241
8242 touch();
8243
8244 mTouchWindow->assertNoEvents();
8245}
8246
8247/**
8248 * This test is testing that a window from a different UID but with same application token doesn't
8249 * block the touch. Apps can share the application token for close UI collaboration for example.
8250 */
8251TEST_F(InputDispatcherUntrustedTouchesTest,
8252 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8253 const sp<FakeWindowHandle>& w =
8254 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8255 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008256 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8257
8258 touch();
8259
8260 mTouchWindow->consumeAnyMotionDown();
8261}
8262
arthurhungb89ccb02020-12-30 16:19:01 +08008263class InputDispatcherDragTests : public InputDispatcherTest {
8264protected:
8265 std::shared_ptr<FakeApplicationHandle> mApp;
8266 sp<FakeWindowHandle> mWindow;
8267 sp<FakeWindowHandle> mSecondWindow;
8268 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008269 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008270 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8271 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008272
8273 void SetUp() override {
8274 InputDispatcherTest::SetUp();
8275 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008276 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008277 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008278
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008279 mSecondWindow =
8280 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008281 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008282
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008283 mSpyWindow =
8284 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008285 mSpyWindow->setSpy(true);
8286 mSpyWindow->setTrustedOverlay(true);
8287 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8288
arthurhungb89ccb02020-12-30 16:19:01 +08008289 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008290 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008291 }
8292
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008293 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8294 switch (fromSource) {
8295 case AINPUT_SOURCE_TOUCHSCREEN:
8296 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8297 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8298 ADISPLAY_ID_DEFAULT, {50, 50}))
8299 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8300 break;
8301 case AINPUT_SOURCE_STYLUS:
8302 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8303 injectMotionEvent(
8304 mDispatcher,
8305 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8306 AINPUT_SOURCE_STYLUS)
8307 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008308 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008309 .x(50)
8310 .y(50))
8311 .build()));
8312 break;
8313 case AINPUT_SOURCE_MOUSE:
8314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8315 injectMotionEvent(
8316 mDispatcher,
8317 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8318 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8319 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008320 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008321 .x(50)
8322 .y(50))
8323 .build()));
8324 break;
8325 default:
8326 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8327 }
arthurhungb89ccb02020-12-30 16:19:01 +08008328
8329 // Window should receive motion event.
8330 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008331 // Spy window should also receive motion event
8332 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008333 }
8334
8335 // Start performing drag, we will create a drag window and transfer touch to it.
8336 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8337 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008338 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008339 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008340 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008341 }
arthurhungb89ccb02020-12-30 16:19:01 +08008342
8343 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008344 mDragWindow =
8345 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008346 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08008347 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008348 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008349
8350 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008351 bool transferred =
8352 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008353 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008354 if (transferred) {
8355 mWindow->consumeMotionCancel();
8356 mDragWindow->consumeMotionDown();
8357 }
8358 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008359 }
8360};
8361
8362TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008363 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008364
8365 // Move on window.
8366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8367 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8368 ADISPLAY_ID_DEFAULT, {50, 50}))
8369 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8370 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8371 mWindow->consumeDragEvent(false, 50, 50);
8372 mSecondWindow->assertNoEvents();
8373
8374 // Move to another window.
8375 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8376 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8377 ADISPLAY_ID_DEFAULT, {150, 50}))
8378 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8379 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8380 mWindow->consumeDragEvent(true, 150, 50);
8381 mSecondWindow->consumeDragEvent(false, 50, 50);
8382
8383 // Move back to original window.
8384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8385 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8386 ADISPLAY_ID_DEFAULT, {50, 50}))
8387 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8388 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8389 mWindow->consumeDragEvent(false, 50, 50);
8390 mSecondWindow->consumeDragEvent(true, -50, 50);
8391
8392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8393 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8394 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8395 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8396 mWindow->assertNoEvents();
8397 mSecondWindow->assertNoEvents();
8398}
8399
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008400TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008401 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008402
8403 // No cancel event after drag start
8404 mSpyWindow->assertNoEvents();
8405
8406 const MotionEvent secondFingerDownEvent =
8407 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8408 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008409 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8410 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008411 .build();
8412 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8413 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8414 InputEventInjectionSync::WAIT_FOR_RESULT))
8415 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8416
8417 // Receives cancel for first pointer after next pointer down
8418 mSpyWindow->consumeMotionCancel();
8419 mSpyWindow->consumeMotionDown();
8420
8421 mSpyWindow->assertNoEvents();
8422}
8423
arthurhungf452d0b2021-01-06 00:19:52 +08008424TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008425 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008426
8427 // Move on window.
8428 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8429 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8430 ADISPLAY_ID_DEFAULT, {50, 50}))
8431 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8432 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8433 mWindow->consumeDragEvent(false, 50, 50);
8434 mSecondWindow->assertNoEvents();
8435
8436 // Move to another window.
8437 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8438 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8439 ADISPLAY_ID_DEFAULT, {150, 50}))
8440 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8441 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8442 mWindow->consumeDragEvent(true, 150, 50);
8443 mSecondWindow->consumeDragEvent(false, 50, 50);
8444
8445 // drop to another window.
8446 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8447 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8448 {150, 50}))
8449 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8450 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008451 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08008452 mWindow->assertNoEvents();
8453 mSecondWindow->assertNoEvents();
8454}
8455
arthurhung6d4bed92021-03-17 11:59:33 +08008456TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008457 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008458
8459 // Move on window and keep button pressed.
8460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8461 injectMotionEvent(mDispatcher,
8462 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8463 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008464 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008465 .build()))
8466 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8467 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8468 mWindow->consumeDragEvent(false, 50, 50);
8469 mSecondWindow->assertNoEvents();
8470
8471 // Move to another window and release button, expect to drop item.
8472 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8473 injectMotionEvent(mDispatcher,
8474 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8475 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008476 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008477 .build()))
8478 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8479 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8480 mWindow->assertNoEvents();
8481 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008482 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08008483
8484 // nothing to the window.
8485 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8486 injectMotionEvent(mDispatcher,
8487 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8488 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008489 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008490 .build()))
8491 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8492 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8493 mWindow->assertNoEvents();
8494 mSecondWindow->assertNoEvents();
8495}
8496
Arthur Hung54745652022-04-20 07:17:41 +00008497TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008498 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008499
8500 // Set second window invisible.
8501 mSecondWindow->setVisible(false);
8502 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8503
8504 // Move on window.
8505 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8506 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8507 ADISPLAY_ID_DEFAULT, {50, 50}))
8508 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8509 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8510 mWindow->consumeDragEvent(false, 50, 50);
8511 mSecondWindow->assertNoEvents();
8512
8513 // Move to another window.
8514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8515 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8516 ADISPLAY_ID_DEFAULT, {150, 50}))
8517 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8518 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8519 mWindow->consumeDragEvent(true, 150, 50);
8520 mSecondWindow->assertNoEvents();
8521
8522 // drop to another window.
8523 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8524 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8525 {150, 50}))
8526 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8527 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008528 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08008529 mWindow->assertNoEvents();
8530 mSecondWindow->assertNoEvents();
8531}
8532
Arthur Hung54745652022-04-20 07:17:41 +00008533TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008534 // Ensure window could track pointerIds if it didn't support split touch.
8535 mWindow->setPreventSplitting(true);
8536
Arthur Hung54745652022-04-20 07:17:41 +00008537 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8538 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8539 {50, 50}))
8540 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8541 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8542
8543 const MotionEvent secondFingerDownEvent =
8544 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8545 .displayId(ADISPLAY_ID_DEFAULT)
8546 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008547 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8548 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008549 .build();
8550 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8551 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8552 InputEventInjectionSync::WAIT_FOR_RESULT))
8553 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008554 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008555
8556 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008557 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008558}
8559
8560TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8561 // First down on second window.
8562 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8563 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8564 {150, 50}))
8565 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8566
8567 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8568
8569 // Second down on first window.
8570 const MotionEvent secondFingerDownEvent =
8571 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8572 .displayId(ADISPLAY_ID_DEFAULT)
8573 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008574 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8575 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008576 .build();
8577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8578 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8579 InputEventInjectionSync::WAIT_FOR_RESULT))
8580 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8581 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8582
8583 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008584 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008585
8586 // Move on window.
8587 const MotionEvent secondFingerMoveEvent =
8588 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8589 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008590 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8591 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008592 .build();
8593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8594 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8595 InputEventInjectionSync::WAIT_FOR_RESULT));
8596 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8597 mWindow->consumeDragEvent(false, 50, 50);
8598 mSecondWindow->consumeMotionMove();
8599
8600 // Release the drag pointer should perform drop.
8601 const MotionEvent secondFingerUpEvent =
8602 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8603 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008604 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8605 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008606 .build();
8607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8608 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8609 InputEventInjectionSync::WAIT_FOR_RESULT));
8610 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008611 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00008612 mWindow->assertNoEvents();
8613 mSecondWindow->consumeMotionMove();
8614}
8615
Arthur Hung3915c1f2022-05-31 07:17:17 +00008616TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008617 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008618
8619 // Update window of second display.
8620 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008621 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008622 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8623
8624 // Let second display has a touch state.
8625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8626 injectMotionEvent(mDispatcher,
8627 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8628 AINPUT_SOURCE_TOUCHSCREEN)
8629 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008630 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008631 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008632 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008633 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008634 // Update window again.
8635 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8636
8637 // Move on window.
8638 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8639 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8640 ADISPLAY_ID_DEFAULT, {50, 50}))
8641 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8642 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8643 mWindow->consumeDragEvent(false, 50, 50);
8644 mSecondWindow->assertNoEvents();
8645
8646 // Move to another window.
8647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8648 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8649 ADISPLAY_ID_DEFAULT, {150, 50}))
8650 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8651 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8652 mWindow->consumeDragEvent(true, 150, 50);
8653 mSecondWindow->consumeDragEvent(false, 50, 50);
8654
8655 // drop to another window.
8656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8657 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8658 {150, 50}))
8659 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8660 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008661 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00008662 mWindow->assertNoEvents();
8663 mSecondWindow->assertNoEvents();
8664}
8665
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008666TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8667 startDrag(true, AINPUT_SOURCE_MOUSE);
8668 // Move on window.
8669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8670 injectMotionEvent(mDispatcher,
8671 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8672 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8673 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008674 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008675 .x(50)
8676 .y(50))
8677 .build()))
8678 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8679 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8680 mWindow->consumeDragEvent(false, 50, 50);
8681 mSecondWindow->assertNoEvents();
8682
8683 // Move to another window.
8684 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8685 injectMotionEvent(mDispatcher,
8686 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8687 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8688 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008689 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008690 .x(150)
8691 .y(50))
8692 .build()))
8693 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8694 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8695 mWindow->consumeDragEvent(true, 150, 50);
8696 mSecondWindow->consumeDragEvent(false, 50, 50);
8697
8698 // drop to another window.
8699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8700 injectMotionEvent(mDispatcher,
8701 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8702 .buttonState(0)
8703 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008704 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008705 .x(150)
8706 .y(50))
8707 .build()))
8708 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8709 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008710 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008711 mWindow->assertNoEvents();
8712 mSecondWindow->assertNoEvents();
8713}
8714
Vishnu Nair062a8672021-09-03 16:07:44 -07008715class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8716
8717TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8718 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008719 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8720 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008721 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008722 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8723 window->setFocusable(true);
8724 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8725 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008726 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008727
8728 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008729 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008730 window->assertNoEvents();
8731
Prabir Pradhan678438e2023-04-13 19:32:51 +00008732 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8733 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008734 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8735 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008736 window->assertNoEvents();
8737
8738 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008739 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008740 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8741
Prabir Pradhan678438e2023-04-13 19:32:51 +00008742 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008743 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8744
Prabir Pradhan678438e2023-04-13 19:32:51 +00008745 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8746 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008747 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8748 window->assertNoEvents();
8749}
8750
8751TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8752 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8753 std::make_shared<FakeApplicationHandle>();
8754 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008755 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8756 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008757 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8758 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008759 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008760 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008761 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8762 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008763 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008764 window->setOwnerInfo(222, 222);
8765 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8766 window->setFocusable(true);
8767 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8768 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008769 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008770
8771 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008772 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008773 window->assertNoEvents();
8774
Prabir Pradhan678438e2023-04-13 19:32:51 +00008775 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8776 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008777 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8778 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008779 window->assertNoEvents();
8780
8781 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008782 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008783 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8784
Prabir Pradhan678438e2023-04-13 19:32:51 +00008785 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008786 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8787
Prabir Pradhan678438e2023-04-13 19:32:51 +00008788 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8789 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008790 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8791 window->assertNoEvents();
8792}
8793
8794TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8795 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8796 std::make_shared<FakeApplicationHandle>();
8797 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008798 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8799 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008800 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8801 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008802 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008803 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008804 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8805 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008806 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008807 window->setOwnerInfo(222, 222);
8808 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8809 window->setFocusable(true);
8810 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8811 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008812 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008813
8814 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008815 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008816 window->assertNoEvents();
8817
Prabir Pradhan678438e2023-04-13 19:32:51 +00008818 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8819 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008820 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8821 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008822 window->assertNoEvents();
8823
8824 // When the window is no longer obscured because it went on top, it should get input
8825 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8826
Prabir Pradhan678438e2023-04-13 19:32:51 +00008827 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008828 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8829
Prabir Pradhan678438e2023-04-13 19:32:51 +00008830 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8831 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008832 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8833 window->assertNoEvents();
8834}
8835
Antonio Kantekf16f2832021-09-28 04:39:20 +00008836class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8837protected:
8838 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008839 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008840 sp<FakeWindowHandle> mWindow;
8841 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008842 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008843
8844 void SetUp() override {
8845 InputDispatcherTest::SetUp();
8846
8847 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008848 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008849 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008850 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008851 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008852 mSecondWindow =
8853 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008854 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008855 mThirdWindow =
8856 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8857 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8858 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008859
8860 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008861 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8862 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8863 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008864 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008865
Antonio Kantek15beb512022-06-13 22:35:41 +00008866 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008867 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008868 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008869 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8870 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008871 mThirdWindow->assertNoEvents();
8872 }
8873
8874 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8875 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008876 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008877 SECOND_DISPLAY_ID)) {
8878 mWindow->assertNoEvents();
8879 mSecondWindow->assertNoEvents();
8880 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008881 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008882 }
8883
Antonio Kantek15beb512022-06-13 22:35:41 +00008884 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid,
8885 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008886 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8887 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008888 mWindow->consumeTouchModeEvent(inTouchMode);
8889 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008890 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008891 }
8892};
8893
Antonio Kantek26defcf2022-02-08 01:12:27 +00008894TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008895 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008896 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8897 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008898 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008899}
8900
Antonio Kantek26defcf2022-02-08 01:12:27 +00008901TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8902 const WindowInfo& windowInfo = *mWindow->getInfo();
8903 int32_t ownerPid = windowInfo.ownerPid;
8904 int32_t ownerUid = windowInfo.ownerUid;
8905 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
8906 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008907 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008908 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008909 mWindow->assertNoEvents();
8910 mSecondWindow->assertNoEvents();
8911}
8912
8913TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8914 const WindowInfo& windowInfo = *mWindow->getInfo();
8915 int32_t ownerPid = windowInfo.ownerPid;
8916 int32_t ownerUid = windowInfo.ownerUid;
8917 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
Antonio Kantek15beb512022-06-13 22:35:41 +00008918 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008919 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008920}
8921
Antonio Kantekf16f2832021-09-28 04:39:20 +00008922TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008923 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008924 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8925 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008926 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008927 mWindow->assertNoEvents();
8928 mSecondWindow->assertNoEvents();
8929}
8930
Antonio Kantek15beb512022-06-13 22:35:41 +00008931TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8932 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8933 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8934 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008935 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008936 mWindow->assertNoEvents();
8937 mSecondWindow->assertNoEvents();
8938 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8939}
8940
Antonio Kantek48710e42022-03-24 14:19:30 -07008941TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8942 // Interact with the window first.
8943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8944 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8945 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8946
8947 // Then remove focus.
8948 mWindow->setFocusable(false);
8949 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8950
8951 // Assert that caller can switch touch mode by owning one of the last interacted window.
8952 const WindowInfo& windowInfo = *mWindow->getInfo();
8953 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8954 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008955 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008956}
8957
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008958class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8959public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008960 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008961 std::shared_ptr<FakeApplicationHandle> application =
8962 std::make_shared<FakeApplicationHandle>();
8963 std::string name = "Fake Spy ";
8964 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008965 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8966 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008967 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008968 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008969 return spy;
8970 }
8971
8972 sp<FakeWindowHandle> createForeground() {
8973 std::shared_ptr<FakeApplicationHandle> application =
8974 std::make_shared<FakeApplicationHandle>();
8975 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008976 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8977 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008978 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008979 return window;
8980 }
8981
8982private:
8983 int mSpyCount{0};
8984};
8985
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008986using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008987/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008988 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8989 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008990TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8991 ScopedSilentDeath _silentDeath;
8992
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008993 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008994 spy->setTrustedOverlay(false);
8995 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8996 ".* not a trusted overlay");
8997}
8998
8999/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009000 * Input injection into a display with a spy window but no foreground windows should succeed.
9001 */
9002TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009003 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009004 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
9005
9006 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9007 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9008 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9009 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9010}
9011
9012/**
9013 * Verify the order in which different input windows receive events. The touched foreground window
9014 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9015 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9016 * receive events before ones belows it.
9017 *
9018 * Here, we set up a scenario with four windows in the following Z order from the top:
9019 * spy1, spy2, window, spy3.
9020 * We then inject an event and verify that the foreground "window" receives it first, followed by
9021 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9022 * window.
9023 */
9024TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9025 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009026 auto spy1 = createSpy();
9027 auto spy2 = createSpy();
9028 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009029 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
9030 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9031 const size_t numChannels = channels.size();
9032
Michael Wright8e9a8562022-02-09 13:44:29 +00009033 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009034 if (!epollFd.ok()) {
9035 FAIL() << "Failed to create epoll fd";
9036 }
9037
9038 for (size_t i = 0; i < numChannels; i++) {
9039 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9040 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9041 FAIL() << "Failed to add fd to epoll";
9042 }
9043 }
9044
9045 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9046 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9047 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9048
9049 std::vector<size_t> eventOrder;
9050 std::vector<struct epoll_event> events(numChannels);
9051 for (;;) {
9052 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9053 (100ms).count());
9054 if (nFds < 0) {
9055 FAIL() << "Failed to call epoll_wait";
9056 }
9057 if (nFds == 0) {
9058 break; // epoll_wait timed out
9059 }
9060 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009061 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009062 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009063 channels[i]->consumeMotionDown();
9064 }
9065 }
9066
9067 // Verify the order in which the events were received.
9068 EXPECT_EQ(3u, eventOrder.size());
9069 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9070 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9071 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9072}
9073
9074/**
9075 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9076 */
9077TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9078 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009079 auto spy = createSpy();
9080 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009081 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9082
9083 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9084 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9085 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9086 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9087 spy->assertNoEvents();
9088}
9089
9090/**
9091 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9092 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9093 * to the window.
9094 */
9095TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9096 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009097 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009098 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
9099 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9100
9101 // Inject an event outside the spy window's touchable region.
9102 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9103 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9104 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9105 window->consumeMotionDown();
9106 spy->assertNoEvents();
9107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9108 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9109 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9110 window->consumeMotionUp();
9111 spy->assertNoEvents();
9112
9113 // Inject an event inside the spy window's touchable region.
9114 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9115 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9116 {5, 10}))
9117 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9118 window->consumeMotionDown();
9119 spy->consumeMotionDown();
9120}
9121
9122/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009123 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009124 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009125 */
9126TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9127 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009128 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009129 auto spy = createSpy();
9130 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009131 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009132 spy->setFrame(Rect{0, 0, 20, 20});
9133 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9134
9135 // Inject an event outside the spy window's frame and touchable region.
9136 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009137 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9138 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009139 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9140 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009141 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009142}
9143
9144/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009145 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9146 * pointers that are down within its bounds.
9147 */
9148TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9149 auto windowLeft = createForeground();
9150 windowLeft->setFrame({0, 0, 100, 200});
9151 auto windowRight = createForeground();
9152 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009153 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009154 spy->setFrame({0, 0, 200, 200});
9155 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
9156
9157 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9158 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9159 {50, 50}))
9160 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9161 windowLeft->consumeMotionDown();
9162 spy->consumeMotionDown();
9163
9164 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009165 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009166 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009167 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9168 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009169 .build();
9170 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9171 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9172 InputEventInjectionSync::WAIT_FOR_RESULT))
9173 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9174 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009175 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009176}
9177
9178/**
9179 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9180 * the spy should receive the second pointer with ACTION_DOWN.
9181 */
9182TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9183 auto window = createForeground();
9184 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009185 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009186 spyRight->setFrame({100, 0, 200, 200});
9187 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
9188
9189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9190 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9191 {50, 50}))
9192 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9193 window->consumeMotionDown();
9194 spyRight->assertNoEvents();
9195
9196 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009197 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009198 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009199 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9200 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009201 .build();
9202 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9203 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9204 InputEventInjectionSync::WAIT_FOR_RESULT))
9205 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009206 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009207 spyRight->consumeMotionDown();
9208}
9209
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009210/**
9211 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9212 * windows should be allowed to control split touch.
9213 */
9214TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009215 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009216 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009217 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009218 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009219
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009220 auto window = createForeground();
9221 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009222
9223 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9224
9225 // First finger down, no window touched.
9226 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9227 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9228 {100, 200}))
9229 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9230 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9231 window->assertNoEvents();
9232
9233 // Second finger down on window, the window should receive touch down.
9234 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009235 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009236 .displayId(ADISPLAY_ID_DEFAULT)
9237 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009238 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9239 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009240 .build();
9241 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9242 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9243 InputEventInjectionSync::WAIT_FOR_RESULT))
9244 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9245
9246 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009247 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009248}
9249
9250/**
9251 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9252 * do not receive key events.
9253 */
9254TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009255 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009256 spy->setFocusable(false);
9257
9258 auto window = createForeground();
9259 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9260 setFocusedWindow(window);
9261 window->consumeFocusEvent(true);
9262
9263 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
9264 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9265 window->consumeKeyDown(ADISPLAY_ID_NONE);
9266
9267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
9268 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9269 window->consumeKeyUp(ADISPLAY_ID_NONE);
9270
9271 spy->assertNoEvents();
9272}
9273
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009274using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9275
9276/**
9277 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9278 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9279 */
9280TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9281 auto window = createForeground();
9282 auto spy1 = createSpy();
9283 auto spy2 = createSpy();
9284 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
9285
9286 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9287 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9288 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9289 window->consumeMotionDown();
9290 spy1->consumeMotionDown();
9291 spy2->consumeMotionDown();
9292
9293 // Pilfer pointers from the second spy window.
9294 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9295 spy2->assertNoEvents();
9296 spy1->consumeMotionCancel();
9297 window->consumeMotionCancel();
9298
9299 // The rest of the gesture should only be sent to the second spy window.
9300 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9301 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9302 ADISPLAY_ID_DEFAULT))
9303 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9304 spy2->consumeMotionMove();
9305 spy1->assertNoEvents();
9306 window->assertNoEvents();
9307}
9308
9309/**
9310 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9311 * in the middle of the gesture.
9312 */
9313TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9314 auto window = createForeground();
9315 auto spy = createSpy();
9316 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9317
9318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9319 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9320 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9321 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9322 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9323
9324 window->releaseChannel();
9325
9326 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9327
9328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9329 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9330 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9331 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9332}
9333
9334/**
9335 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9336 * the spy, but not to any other windows.
9337 */
9338TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9339 auto spy = createSpy();
9340 auto window = createForeground();
9341
9342 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9343
9344 // First finger down on the window and the spy.
9345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9346 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9347 {100, 200}))
9348 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9349 spy->consumeMotionDown();
9350 window->consumeMotionDown();
9351
9352 // Spy window pilfers the pointers.
9353 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9354 window->consumeMotionCancel();
9355
9356 // Second finger down on the window and spy, but the window should not receive the pointer down.
9357 const MotionEvent secondFingerDownEvent =
9358 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9359 .displayId(ADISPLAY_ID_DEFAULT)
9360 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009361 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9362 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009363 .build();
9364 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9365 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9366 InputEventInjectionSync::WAIT_FOR_RESULT))
9367 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9368
Harry Cutts33476232023-01-30 19:57:29 +00009369 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009370
9371 // Third finger goes down outside all windows, so injection should fail.
9372 const MotionEvent thirdFingerDownEvent =
9373 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9374 .displayId(ADISPLAY_ID_DEFAULT)
9375 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009376 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9377 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9378 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009379 .build();
9380 ASSERT_EQ(InputEventInjectionResult::FAILED,
9381 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9382 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009383 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009384
9385 spy->assertNoEvents();
9386 window->assertNoEvents();
9387}
9388
9389/**
9390 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9391 */
9392TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9393 auto spy = createSpy();
9394 spy->setFrame(Rect(0, 0, 100, 100));
9395 auto window = createForeground();
9396 window->setFrame(Rect(0, 0, 200, 200));
9397
9398 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9399
9400 // First finger down on the window only
9401 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9402 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9403 {150, 150}))
9404 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9405 window->consumeMotionDown();
9406
9407 // Second finger down on the spy and window
9408 const MotionEvent secondFingerDownEvent =
9409 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9410 .displayId(ADISPLAY_ID_DEFAULT)
9411 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009412 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9413 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009414 .build();
9415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9416 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9417 InputEventInjectionSync::WAIT_FOR_RESULT))
9418 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9419 spy->consumeMotionDown();
9420 window->consumeMotionPointerDown(1);
9421
9422 // Third finger down on the spy and window
9423 const MotionEvent thirdFingerDownEvent =
9424 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9425 .displayId(ADISPLAY_ID_DEFAULT)
9426 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009427 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9428 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9429 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009430 .build();
9431 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9432 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9433 InputEventInjectionSync::WAIT_FOR_RESULT))
9434 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9435 spy->consumeMotionPointerDown(1);
9436 window->consumeMotionPointerDown(2);
9437
9438 // Spy window pilfers the pointers.
9439 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9440 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9441 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9442
9443 spy->assertNoEvents();
9444 window->assertNoEvents();
9445}
9446
9447/**
9448 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9449 * other windows should be canceled. If this results in the cancellation of all pointers for some
9450 * window, then that window should receive ACTION_CANCEL.
9451 */
9452TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9453 auto spy = createSpy();
9454 spy->setFrame(Rect(0, 0, 100, 100));
9455 auto window = createForeground();
9456 window->setFrame(Rect(0, 0, 200, 200));
9457
9458 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9459
9460 // First finger down on both spy and window
9461 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9462 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9463 {10, 10}))
9464 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9465 window->consumeMotionDown();
9466 spy->consumeMotionDown();
9467
9468 // Second finger down on the spy and window
9469 const MotionEvent secondFingerDownEvent =
9470 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9471 .displayId(ADISPLAY_ID_DEFAULT)
9472 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009473 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9474 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009475 .build();
9476 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9477 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9478 InputEventInjectionSync::WAIT_FOR_RESULT))
9479 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9480 spy->consumeMotionPointerDown(1);
9481 window->consumeMotionPointerDown(1);
9482
9483 // Spy window pilfers the pointers.
9484 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9485 window->consumeMotionCancel();
9486
9487 spy->assertNoEvents();
9488 window->assertNoEvents();
9489}
9490
9491/**
9492 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9493 * be sent to other windows
9494 */
9495TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9496 auto spy = createSpy();
9497 spy->setFrame(Rect(0, 0, 100, 100));
9498 auto window = createForeground();
9499 window->setFrame(Rect(0, 0, 200, 200));
9500
9501 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9502
9503 // First finger down on both window and spy
9504 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9505 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9506 {10, 10}))
9507 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9508 window->consumeMotionDown();
9509 spy->consumeMotionDown();
9510
9511 // Spy window pilfers the pointers.
9512 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9513 window->consumeMotionCancel();
9514
9515 // Second finger down on the window only
9516 const MotionEvent secondFingerDownEvent =
9517 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9518 .displayId(ADISPLAY_ID_DEFAULT)
9519 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009520 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9521 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009522 .build();
9523 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9524 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9525 InputEventInjectionSync::WAIT_FOR_RESULT))
9526 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9527 window->consumeMotionDown();
9528 window->assertNoEvents();
9529
9530 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9531 spy->consumeMotionMove();
9532 spy->assertNoEvents();
9533}
9534
Prabir Pradhand65552b2021-10-07 11:23:50 -07009535class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9536public:
9537 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9538 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9539 std::make_shared<FakeApplicationHandle>();
9540 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009541 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9542 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009543 overlay->setFocusable(false);
9544 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009545 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009546 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009547 overlay->setTrustedOverlay(true);
9548
9549 std::shared_ptr<FakeApplicationHandle> application =
9550 std::make_shared<FakeApplicationHandle>();
9551 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009552 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9553 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009554 window->setFocusable(true);
9555 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009556
9557 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9558 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9559 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009560 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009561 return {std::move(overlay), std::move(window)};
9562 }
9563
9564 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009565 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009566 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009567 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009568 }
9569
9570 void sendStylusEvent(int32_t action) {
9571 NotifyMotionArgs motionArgs =
9572 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9573 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009574 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009575 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009576 }
9577};
9578
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009579using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9580
9581TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
9582 ScopedSilentDeath _silentDeath;
9583
Prabir Pradhand65552b2021-10-07 11:23:50 -07009584 auto [overlay, window] = setupStylusOverlayScenario();
9585 overlay->setTrustedOverlay(false);
9586 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9587 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9588 ".* not a trusted overlay");
9589}
9590
9591TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9592 auto [overlay, window] = setupStylusOverlayScenario();
9593 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9594
9595 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9596 overlay->consumeMotionDown();
9597 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9598 overlay->consumeMotionUp();
9599
9600 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9601 window->consumeMotionDown();
9602 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9603 window->consumeMotionUp();
9604
9605 overlay->assertNoEvents();
9606 window->assertNoEvents();
9607}
9608
9609TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9610 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009611 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009612 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9613
9614 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9615 overlay->consumeMotionDown();
9616 window->consumeMotionDown();
9617 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9618 overlay->consumeMotionUp();
9619 window->consumeMotionUp();
9620
9621 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9622 window->consumeMotionDown();
9623 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9624 window->consumeMotionUp();
9625
9626 overlay->assertNoEvents();
9627 window->assertNoEvents();
9628}
9629
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009630/**
9631 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9632 * The scenario is as follows:
9633 * - The stylus interceptor overlay is configured as a spy window.
9634 * - The stylus interceptor spy receives the start of a new stylus gesture.
9635 * - It pilfers pointers and then configures itself to no longer be a spy.
9636 * - The stylus interceptor continues to receive the rest of the gesture.
9637 */
9638TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9639 auto [overlay, window] = setupStylusOverlayScenario();
9640 overlay->setSpy(true);
9641 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9642
9643 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9644 overlay->consumeMotionDown();
9645 window->consumeMotionDown();
9646
9647 // The interceptor pilfers the pointers.
9648 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9649 window->consumeMotionCancel();
9650
9651 // The interceptor configures itself so that it is no longer a spy.
9652 overlay->setSpy(false);
9653 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9654
9655 // It continues to receive the rest of the stylus gesture.
9656 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9657 overlay->consumeMotionMove();
9658 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9659 overlay->consumeMotionUp();
9660
9661 window->assertNoEvents();
9662}
9663
Prabir Pradhan5735a322022-04-11 17:23:34 +00009664struct User {
9665 int32_t mPid;
9666 int32_t mUid;
9667 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9668 std::unique_ptr<InputDispatcher>& mDispatcher;
9669
9670 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
9671 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9672
9673 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9674 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9675 ADISPLAY_ID_DEFAULT, {100, 200},
9676 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9677 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9678 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9679 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9680 }
9681
9682 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009683 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009684 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009685 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009686 mPolicyFlags);
9687 }
9688
9689 sp<FakeWindowHandle> createWindow() const {
9690 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9691 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009692 sp<FakeWindowHandle> window =
9693 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9694 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009695 window->setOwnerInfo(mPid, mUid);
9696 return window;
9697 }
9698};
9699
9700using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9701
9702TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
9703 auto owner = User(mDispatcher, 10, 11);
9704 auto window = owner.createWindow();
9705 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9706
9707 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9708 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9709 window->consumeMotionDown();
9710
9711 setFocusedWindow(window);
9712 window->consumeFocusEvent(true);
9713
9714 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9715 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9716 window->consumeKeyDown(ADISPLAY_ID_NONE);
9717}
9718
9719TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
9720 auto owner = User(mDispatcher, 10, 11);
9721 auto window = owner.createWindow();
9722 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9723
9724 auto rando = User(mDispatcher, 20, 21);
9725 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9726 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9727
9728 setFocusedWindow(window);
9729 window->consumeFocusEvent(true);
9730
9731 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9732 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9733 window->assertNoEvents();
9734}
9735
9736TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
9737 auto owner = User(mDispatcher, 10, 11);
9738 auto window = owner.createWindow();
9739 auto spy = owner.createWindow();
9740 spy->setSpy(true);
9741 spy->setTrustedOverlay(true);
9742 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9743
9744 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9745 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9746 spy->consumeMotionDown();
9747 window->consumeMotionDown();
9748}
9749
9750TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
9751 auto owner = User(mDispatcher, 10, 11);
9752 auto window = owner.createWindow();
9753
9754 auto rando = User(mDispatcher, 20, 21);
9755 auto randosSpy = rando.createWindow();
9756 randosSpy->setSpy(true);
9757 randosSpy->setTrustedOverlay(true);
9758 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9759
9760 // The event is targeted at owner's window, so injection should succeed, but the spy should
9761 // not receive the event.
9762 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9763 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9764 randosSpy->assertNoEvents();
9765 window->consumeMotionDown();
9766}
9767
9768TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
9769 auto owner = User(mDispatcher, 10, 11);
9770 auto window = owner.createWindow();
9771
9772 auto rando = User(mDispatcher, 20, 21);
9773 auto randosSpy = rando.createWindow();
9774 randosSpy->setSpy(true);
9775 randosSpy->setTrustedOverlay(true);
9776 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9777
9778 // A user that has injection permission can inject into any window.
9779 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9780 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9781 ADISPLAY_ID_DEFAULT));
9782 randosSpy->consumeMotionDown();
9783 window->consumeMotionDown();
9784
9785 setFocusedWindow(randosSpy);
9786 randosSpy->consumeFocusEvent(true);
9787
9788 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9789 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9790 window->assertNoEvents();
9791}
9792
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009793TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00009794 auto owner = User(mDispatcher, 10, 11);
9795 auto window = owner.createWindow();
9796
9797 auto rando = User(mDispatcher, 20, 21);
9798 auto randosWindow = rando.createWindow();
9799 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9800 randosWindow->setWatchOutsideTouch(true);
9801 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9802
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009803 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009804 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9805 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9806 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009807 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +00009808}
9809
Garfield Tane84e6f92019-08-29 17:28:41 -07009810} // namespace android::inputdispatcher