blob: 8a49ba1542f017b998433b2037fe3be56268d961 [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
arthurhungf452d0b2021-01-06 00:19:52 +0800386 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
387 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800388 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800389 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800390 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800391 }
392
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800393 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
394 std::unique_lock lock(mLock);
395 base::ScopedLockAssertion assumeLocked(mLock);
396 std::optional<sp<IBinder>> receivedToken =
397 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
398 mNotifyInputChannelBroken);
399 ASSERT_TRUE(receivedToken.has_value());
400 ASSERT_EQ(token, *receivedToken);
401 }
402
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800403 /**
404 * Set policy timeout. A value of zero means next key will not be intercepted.
405 */
406 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
407 mInterceptKeyTimeout = timeout;
408 }
409
Josep del Riob3981622023-04-18 15:49:45 +0000410 void assertUserActivityPoked() {
411 std::scoped_lock lock(mLock);
412 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
413 }
414
415 void assertUserActivityNotPoked() {
416 std::scoped_lock lock(mLock);
417 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
418 }
419
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000420 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<int32_t> uids) {
421 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
422 }
423
424 void assertNotifyDeviceInteractionWasNotCalled() {
425 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
426 }
427
Michael Wrightd02c5b62014-02-10 15:10:22 -0800428private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700429 std::mutex mLock;
430 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
431 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
432 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
433 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800434
Prabir Pradhan99987712020-11-10 18:43:05 -0800435 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000436
437 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800438
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700439 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700440 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800441 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
442 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700443 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800444 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
445 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700446
arthurhungf452d0b2021-01-06 00:19:52 +0800447 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800448 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000449 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800450
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800451 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
452
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000453 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<int32_t /*uid*/>>> mNotifiedInteractions;
454
Prabir Pradhanedd96402022-02-15 01:46:16 -0800455 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
456 // for a specific container to become non-empty. When the container is non-empty, return the
457 // first entry from the container and erase it.
458 template <class T>
459 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
460 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
461 // If there is an ANR, Dispatcher won't be idle because there are still events
462 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
463 // before checking if ANR was called.
464 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
465 // to provide it some time to act. 100ms seems reasonable.
466 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
467 const std::chrono::time_point start = std::chrono::steady_clock::now();
468 std::optional<T> token =
469 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
470 if (!token.has_value()) {
471 ADD_FAILURE() << "Did not receive the ANR callback";
472 return {};
473 }
474
475 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
476 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
477 // the dispatcher started counting before this function was called
478 if (std::chrono::abs(timeout - waited) > 100ms) {
479 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
480 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
481 << "ms, but waited "
482 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
483 << "ms instead";
484 }
485 return *token;
486 }
487
488 template <class T>
489 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
490 std::queue<T>& storage,
491 std::unique_lock<std::mutex>& lock,
492 std::condition_variable& condition)
493 REQUIRES(mLock) {
494 condition.wait_for(lock, timeout,
495 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
496 if (storage.empty()) {
497 ADD_FAILURE() << "Did not receive the expected callback";
498 return std::nullopt;
499 }
500 T item = storage.front();
501 storage.pop();
502 return std::make_optional(item);
503 }
504
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600505 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700506 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800507 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800508 }
509
Prabir Pradhanedd96402022-02-15 01:46:16 -0800510 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
511 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700512 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800513 ASSERT_TRUE(pid.has_value());
514 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700515 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500516 }
517
Prabir Pradhanedd96402022-02-15 01:46:16 -0800518 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
519 std::optional<int32_t> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500520 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800521 ASSERT_TRUE(pid.has_value());
522 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500523 mNotifyAnr.notify_all();
524 }
525
526 void notifyNoFocusedWindowAnr(
527 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
528 std::scoped_lock lock(mLock);
529 mAnrApplications.push(applicationHandle);
530 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800531 }
532
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800533 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
534 std::scoped_lock lock(mLock);
535 mBrokenInputChannels.push(connectionToken);
536 mNotifyInputChannelBroken.notify_all();
537 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800538
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600539 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700540
Chris Yef59a2f42020-10-16 12:55:26 -0700541 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
542 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
543 const std::vector<float>& values) override {}
544
545 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
546 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000547
Chris Yefb552902021-02-03 17:18:37 -0800548 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
549
Prabir Pradhana41d2442023-04-20 21:30:40 +0000550 InputDispatcherConfiguration getDispatcherConfiguration() override { return mConfig; }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800551
Prabir Pradhana41d2442023-04-20 21:30:40 +0000552 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700553 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000554 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700555 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000556 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
557 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800558 break;
559 }
560
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700561 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000562 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
563 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800564 break;
565 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700566 default: {
567 ADD_FAILURE() << "Should only filter keys or motions";
568 break;
569 }
Jackal Guof9696682018-10-05 12:23:23 +0800570 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800571 return true;
572 }
573
Prabir Pradhana41d2442023-04-20 21:30:40 +0000574 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
575 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800576 // Clear intercept state when we handled the event.
577 mInterceptKeyTimeout = 0ms;
578 }
579 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800580
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600581 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800582
Prabir Pradhana41d2442023-04-20 21:30:40 +0000583 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800584 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
585 // Clear intercept state so we could dispatch the event in next wake.
586 mInterceptKeyTimeout = 0ms;
587 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800588 }
589
Prabir Pradhana41d2442023-04-20 21:30:40 +0000590 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
591 uint32_t) override {
592 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800593 }
594
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600595 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
596 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700597 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800598 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
599 * essentially a passthrough for notifySwitch.
600 */
Harry Cutts33476232023-01-30 19:57:29 +0000601 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800602 }
603
Josep del Riob3981622023-04-18 15:49:45 +0000604 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
605 std::scoped_lock lock(mLock);
606 mPokedUserActivity = true;
607 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800608
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600609 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700610 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700611 mOnPointerDownToken = newToken;
612 }
613
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000614 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800615 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000616 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800617 mPointerCaptureChangedCondition.notify_all();
618 }
619
arthurhungf452d0b2021-01-06 00:19:52 +0800620 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
621 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800622 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800623 mDropTargetWindowToken = token;
624 }
625
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000626 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
627 const std::set<int32_t>& uids) override {
628 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
629 }
630
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700631 void assertFilterInputEventWasCalledInternal(
632 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700633 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800634 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700635 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800636 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800637 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800638};
639
Michael Wrightd02c5b62014-02-10 15:10:22 -0800640// --- InputDispatcherTest ---
641
642class InputDispatcherTest : public testing::Test {
643protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000644 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700645 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800646
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000647 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000648 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
649 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800650 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000651 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700652 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800653 }
654
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000655 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700656 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000657 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700658 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800659 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700660
661 /**
662 * Used for debugging when writing the test
663 */
664 void dumpDispatcherState() {
665 std::string dump;
666 mDispatcher->dump(dump);
667 std::stringstream ss(dump);
668 std::string to;
669
670 while (std::getline(ss, to, '\n')) {
671 ALOGE("%s", to.c_str());
672 }
673 }
Vishnu Nair958da932020-08-21 17:12:37 -0700674
Chavi Weingarten847e8512023-03-29 00:26:09 +0000675 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700676 FocusRequest request;
677 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000678 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700679 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
680 request.displayId = window->getInfo()->displayId;
681 mDispatcher->setFocusedWindow(request);
682 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800683};
684
Michael Wrightd02c5b62014-02-10 15:10:22 -0800685TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
686 KeyEvent event;
687
688 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800689 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
690 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600691 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
692 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800693 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000694 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000695 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800696 << "Should reject key events with undefined action.";
697
698 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800699 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
700 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600701 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800702 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000703 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000704 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800705 << "Should reject key events with ACTION_MULTIPLE.";
706}
707
708TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
709 MotionEvent event;
710 PointerProperties pointerProperties[MAX_POINTERS + 1];
711 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800712 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800713 pointerProperties[i].clear();
714 pointerProperties[i].id = i;
715 pointerCoords[i].clear();
716 }
717
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800718 // Some constants commonly used below
719 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
720 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
721 constexpr int32_t metaState = AMETA_NONE;
722 constexpr MotionClassification classification = MotionClassification::NONE;
723
chaviw9eaa22c2020-07-01 16:21:27 -0700724 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800725 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800726 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700727 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
728 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700729 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
730 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700731 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800732 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000733 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000734 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800735 << "Should reject motion events with undefined action.";
736
737 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800738 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800739 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
740 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
741 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
742 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500743 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800744 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000745 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000746 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800747 << "Should reject motion events with pointer down index too large.";
748
Garfield Tanfbe732e2020-01-24 11:26:14 -0800749 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700750 AMOTION_EVENT_ACTION_POINTER_DOWN |
751 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700752 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
753 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700754 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500755 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800756 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000757 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000758 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800759 << "Should reject motion events with pointer down index too small.";
760
761 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800762 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800763 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
764 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
765 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
766 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500767 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800768 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000769 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000770 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800771 << "Should reject motion events with pointer up index too large.";
772
Garfield Tanfbe732e2020-01-24 11:26:14 -0800773 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700774 AMOTION_EVENT_ACTION_POINTER_UP |
775 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700776 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
777 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700778 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500779 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800780 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000781 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000782 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800783 << "Should reject motion events with pointer up index too small.";
784
785 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800786 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
787 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700788 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700789 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
790 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700791 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800792 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000793 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000794 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800795 << "Should reject motion events with 0 pointers.";
796
Garfield Tanfbe732e2020-01-24 11:26:14 -0800797 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
798 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700799 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700800 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
801 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700802 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800803 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000804 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000805 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800806 << "Should reject motion events with more than MAX_POINTERS pointers.";
807
808 // Rejects motion events with invalid pointer ids.
809 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800810 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
811 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700812 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700813 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
814 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700815 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800816 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000817 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000818 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800819 << "Should reject motion events with pointer ids less than 0.";
820
821 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800822 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
823 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700824 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700825 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
826 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700827 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800828 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000829 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000830 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800831 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
832
833 // Rejects motion events with duplicate pointer ids.
834 pointerProperties[0].id = 1;
835 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800836 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
837 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700838 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700839 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
840 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700841 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800842 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000843 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000844 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800845 << "Should reject motion events with duplicate pointer ids.";
846}
847
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800848/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
849
850TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
851 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000852 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800853 ASSERT_TRUE(mDispatcher->waitForIdle());
854
855 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
856}
857
858TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000859 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
860 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000861 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800862
863 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
864 args.policyFlags |= POLICY_FLAG_TRUSTED;
865 mFakePolicy->assertNotifySwitchWasCalled(args);
866}
867
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700868namespace {
869
Arthur Hungb92218b2018-08-14 12:00:21 +0800870// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700871static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700872// Default input dispatching timeout if there is no focused application or paused window
873// from which to determine an appropriate dispatching timeout.
874static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
875 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
876 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800877
878class FakeApplicationHandle : public InputApplicationHandle {
879public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700880 FakeApplicationHandle() {
881 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700882 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500883 mInfo.dispatchingTimeoutMillis =
884 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700885 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800886 virtual ~FakeApplicationHandle() {}
887
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000888 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700889
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500890 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
891 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700892 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800893};
894
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800895class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800896public:
Garfield Tan15601662020-09-22 15:32:38 -0700897 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800898 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700899 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800900 }
901
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800902 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700903 InputEvent* event;
904 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
905 if (!consumeSeq) {
906 return nullptr;
907 }
908 finishEvent(*consumeSeq);
909 return event;
910 }
911
912 /**
913 * Receive an event without acknowledging it.
914 * Return the sequence number that could later be used to send finished signal.
915 */
916 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800917 uint32_t consumeSeq;
918 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800919
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800920 std::chrono::time_point start = std::chrono::steady_clock::now();
921 status_t status = WOULD_BLOCK;
922 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000923 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800924 &event);
925 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
926 if (elapsed > 100ms) {
927 break;
928 }
929 }
930
931 if (status == WOULD_BLOCK) {
932 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700933 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800934 }
935
936 if (status != OK) {
937 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700938 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800939 }
940 if (event == nullptr) {
941 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700942 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800943 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700944 if (outEvent != nullptr) {
945 *outEvent = event;
946 }
947 return consumeSeq;
948 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800949
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700950 /**
951 * To be used together with "receiveEvent" to complete the consumption of an event.
952 */
953 void finishEvent(uint32_t consumeSeq) {
954 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
955 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800956 }
957
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000958 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
959 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
960 ASSERT_EQ(OK, status);
961 }
962
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700963 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000964 std::optional<int32_t> expectedDisplayId,
965 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800966 InputEvent* event = consume();
967
968 ASSERT_NE(nullptr, event) << mName.c_str()
969 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800970 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700971 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
972 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800973
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000974 if (expectedDisplayId.has_value()) {
975 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
976 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800977
Tiger Huang8664f8c2018-10-11 19:14:35 +0800978 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700979 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800980 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
981 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000982 if (expectedFlags.has_value()) {
983 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
984 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800985 break;
986 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700987 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800988 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000989 assertMotionAction(expectedAction, motionEvent.getAction());
990
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000991 if (expectedFlags.has_value()) {
992 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
993 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800994 break;
995 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700996 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100997 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
998 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700999 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -08001000 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
1001 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001002 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001003 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
1004 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001005 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001006 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1007 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001008 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001009 }
1010
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001011 MotionEvent* consumeMotion() {
1012 InputEvent* event = consume();
1013
1014 if (event == nullptr) {
1015 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1016 return nullptr;
1017 }
1018
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001019 if (event->getType() != InputEventType::MOTION) {
1020 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001021 return nullptr;
1022 }
1023 return static_cast<MotionEvent*>(event);
1024 }
1025
1026 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1027 MotionEvent* motionEvent = consumeMotion();
1028 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1029 ASSERT_THAT(*motionEvent, matcher);
1030 }
1031
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001032 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1033 InputEvent* event = consume();
1034 ASSERT_NE(nullptr, event) << mName.c_str()
1035 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001036 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1037 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001038
1039 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1040 << mName.c_str() << ": event displayId should always be NONE.";
1041
1042 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1043 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001044 }
1045
Prabir Pradhan99987712020-11-10 18:43:05 -08001046 void consumeCaptureEvent(bool hasCapture) {
1047 const InputEvent* event = consume();
1048 ASSERT_NE(nullptr, event) << mName.c_str()
1049 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001050 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1051 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001052
1053 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1054 << mName.c_str() << ": event displayId should always be NONE.";
1055
1056 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1057 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1058 }
1059
arthurhungb89ccb02020-12-30 16:19:01 +08001060 void consumeDragEvent(bool isExiting, float x, float y) {
1061 const InputEvent* event = consume();
1062 ASSERT_NE(nullptr, event) << mName.c_str()
1063 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001064 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001065
1066 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1067 << mName.c_str() << ": event displayId should always be NONE.";
1068
1069 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1070 EXPECT_EQ(isExiting, dragEvent.isExiting());
1071 EXPECT_EQ(x, dragEvent.getX());
1072 EXPECT_EQ(y, dragEvent.getY());
1073 }
1074
Antonio Kantekf16f2832021-09-28 04:39:20 +00001075 void consumeTouchModeEvent(bool inTouchMode) {
1076 const InputEvent* event = consume();
1077 ASSERT_NE(nullptr, event) << mName.c_str()
1078 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001079 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1080 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001081
1082 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1083 << mName.c_str() << ": event displayId should always be NONE.";
1084 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1085 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1086 }
1087
chaviwd1c23182019-12-20 18:44:56 -08001088 void assertNoEvents() {
1089 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001090 if (event == nullptr) {
1091 return;
1092 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001093 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001094 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1095 ADD_FAILURE() << "Received key event "
1096 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001097 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001098 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1099 ADD_FAILURE() << "Received motion event "
1100 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001101 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001102 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1103 ADD_FAILURE() << "Received focus event, hasFocus = "
1104 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001105 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001106 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1107 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1108 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001109 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001110 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1111 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1112 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001113 }
1114 FAIL() << mName.c_str()
1115 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001116 }
1117
1118 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1119
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001120 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1121
chaviwd1c23182019-12-20 18:44:56 -08001122protected:
1123 std::unique_ptr<InputConsumer> mConsumer;
1124 PreallocatedInputEventFactory mEventFactory;
1125
1126 std::string mName;
1127};
1128
chaviw3277faf2021-05-19 16:45:23 -05001129class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001130public:
1131 static const int32_t WIDTH = 600;
1132 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001133
Chris Yea209fde2020-07-22 13:54:51 -07001134 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001135 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001136 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001137 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001138 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001139 base::Result<std::unique_ptr<InputChannel>> channel =
1140 dispatcher->createInputChannel(name);
1141 token = (*channel)->getConnectionToken();
1142 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001143 }
1144
1145 inputApplicationHandle->updateInfo();
1146 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1147
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001148 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001149 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001150 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001151 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001152 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001153 mInfo.frameLeft = 0;
1154 mInfo.frameTop = 0;
1155 mInfo.frameRight = WIDTH;
1156 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001157 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001158 mInfo.globalScaleFactor = 1.0;
1159 mInfo.touchableRegion.clear();
1160 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001161 mInfo.ownerPid = WINDOW_PID;
1162 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001163 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001164 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001165 }
1166
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001167 sp<FakeWindowHandle> clone(int32_t displayId) {
1168 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1169 handle->mInfo = mInfo;
1170 handle->mInfo.displayId = displayId;
1171 handle->mInfo.id = sId++;
1172 handle->mInputReceiver = mInputReceiver;
1173 return handle;
1174 }
1175
1176 /**
1177 * This is different from clone, because clone will make a "mirror" window - a window with the
1178 * same token, but a different ID. The original window and the clone window are allowed to be
1179 * sent to the dispatcher at the same time - they can coexist inside the dispatcher.
1180 * This function will create a different object of WindowInfoHandle, but with the same
1181 * properties as the original object - including the ID.
1182 * You can use either the old or the new object to consume the events.
1183 * IMPORTANT: The duplicated object is supposed to replace the original object, and not appear
1184 * at the same time inside dispatcher.
1185 */
1186 sp<FakeWindowHandle> duplicate() {
1187 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mName);
1188 handle->mInfo = mInfo;
1189 handle->mInputReceiver = mInputReceiver;
Arthur Hungabbb9d82021-09-01 14:52:30 +00001190 return handle;
1191 }
1192
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001193 void setTouchable(bool touchable) {
1194 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1195 }
chaviwd1c23182019-12-20 18:44:56 -08001196
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001197 void setFocusable(bool focusable) {
1198 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1199 }
1200
1201 void setVisible(bool visible) {
1202 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1203 }
Vishnu Nair958da932020-08-21 17:12:37 -07001204
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001205 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001206 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001207 }
1208
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001209 void setPaused(bool paused) {
1210 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1211 }
1212
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001213 void setPreventSplitting(bool preventSplitting) {
1214 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001215 }
1216
1217 void setSlippery(bool slippery) {
1218 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1219 }
1220
1221 void setWatchOutsideTouch(bool watchOutside) {
1222 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1223 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001224
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001225 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1226
1227 void setInterceptsStylus(bool interceptsStylus) {
1228 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1229 }
1230
1231 void setDropInput(bool dropInput) {
1232 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1233 }
1234
1235 void setDropInputIfObscured(bool dropInputIfObscured) {
1236 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1237 }
1238
1239 void setNoInputChannel(bool noInputChannel) {
1240 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1241 }
1242
Josep del Riob3981622023-04-18 15:49:45 +00001243 void setDisableUserActivity(bool disableUserActivity) {
1244 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1245 }
1246
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001247 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1248
chaviw3277faf2021-05-19 16:45:23 -05001249 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001250
Bernardo Rufino7393d172021-02-26 13:56:11 +00001251 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1252
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001253 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001254 mInfo.frameLeft = frame.left;
1255 mInfo.frameTop = frame.top;
1256 mInfo.frameRight = frame.right;
1257 mInfo.frameBottom = frame.bottom;
1258 mInfo.touchableRegion.clear();
1259 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001260
1261 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1262 ui::Transform translate;
1263 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1264 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001265 }
1266
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001267 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1268
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001269 void setIsWallpaper(bool isWallpaper) {
1270 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1271 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001272
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001273 void setDupTouchToWallpaper(bool hasWallpaper) {
1274 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1275 }
chaviwd1c23182019-12-20 18:44:56 -08001276
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001277 void setTrustedOverlay(bool trustedOverlay) {
1278 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1279 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001280
chaviw9eaa22c2020-07-01 16:21:27 -07001281 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1282 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1283 }
1284
1285 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001286
yunho.shinf4a80b82020-11-16 21:13:57 +09001287 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1288
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001289 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001290 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001291 }
1292
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001293 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001294 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001295 }
1296
Svet Ganov5d3bc372020-01-26 23:11:07 -08001297 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001298 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001299 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1300 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001301 }
1302
1303 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001304 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001305 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1306 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001307 }
1308
1309 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001310 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001311 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1312 }
1313
1314 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1315 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001316 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001317 expectedFlags);
1318 }
1319
Svet Ganov5d3bc372020-01-26 23:11:07 -08001320 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001321 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1322 int32_t expectedFlags = 0) {
1323 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1324 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001325 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001326 }
1327
1328 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001329 int32_t expectedFlags = 0) {
1330 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1331 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001332 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001333 }
1334
1335 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001336 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001337 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001338 expectedFlags);
1339 }
1340
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001341 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1342 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001343 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001344 expectedFlags);
1345 }
1346
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001347 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1348 int32_t expectedFlags = 0) {
1349 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001350 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001351 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001352 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1353 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1354 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1355 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1356 }
1357
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001358 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1359 ASSERT_NE(mInputReceiver, nullptr)
1360 << "Cannot consume events from a window with no receiver";
1361 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1362 }
1363
Prabir Pradhan99987712020-11-10 18:43:05 -08001364 void consumeCaptureEvent(bool hasCapture) {
1365 ASSERT_NE(mInputReceiver, nullptr)
1366 << "Cannot consume events from a window with no receiver";
1367 mInputReceiver->consumeCaptureEvent(hasCapture);
1368 }
1369
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001370 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1371 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001372 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001373 ASSERT_THAT(*motionEvent, matcher);
1374 }
1375
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001376 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001377 std::optional<int32_t> expectedDisplayId,
1378 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001379 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1380 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1381 expectedFlags);
1382 }
1383
arthurhungb89ccb02020-12-30 16:19:01 +08001384 void consumeDragEvent(bool isExiting, float x, float y) {
1385 mInputReceiver->consumeDragEvent(isExiting, x, y);
1386 }
1387
Antonio Kantekf16f2832021-09-28 04:39:20 +00001388 void consumeTouchModeEvent(bool inTouchMode) {
1389 ASSERT_NE(mInputReceiver, nullptr)
1390 << "Cannot consume events from a window with no receiver";
1391 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1392 }
1393
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001394 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001395 if (mInputReceiver == nullptr) {
1396 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1397 return std::nullopt;
1398 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001399 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001400 }
1401
1402 void finishEvent(uint32_t sequenceNum) {
1403 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1404 mInputReceiver->finishEvent(sequenceNum);
1405 }
1406
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001407 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1408 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1409 mInputReceiver->sendTimeline(inputEventId, timeline);
1410 }
1411
chaviwaf87b3e2019-10-01 16:59:28 -07001412 InputEvent* consume() {
1413 if (mInputReceiver == nullptr) {
1414 return nullptr;
1415 }
1416 return mInputReceiver->consume();
1417 }
1418
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001419 MotionEvent* consumeMotion() {
1420 InputEvent* event = consume();
1421 if (event == nullptr) {
1422 ADD_FAILURE() << "Consume failed : no event";
1423 return nullptr;
1424 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001425 if (event->getType() != InputEventType::MOTION) {
1426 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001427 return nullptr;
1428 }
1429 return static_cast<MotionEvent*>(event);
1430 }
1431
Arthur Hungb92218b2018-08-14 12:00:21 +08001432 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001433 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001434 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001435 return; // Can't receive events if the window does not have input channel
1436 }
1437 ASSERT_NE(nullptr, mInputReceiver)
1438 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001439 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001440 }
1441
chaviwaf87b3e2019-10-01 16:59:28 -07001442 sp<IBinder> getToken() { return mInfo.token; }
1443
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001444 const std::string& getName() { return mName; }
1445
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001446 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1447 mInfo.ownerPid = ownerPid;
1448 mInfo.ownerUid = ownerUid;
1449 }
1450
Prabir Pradhanedd96402022-02-15 01:46:16 -08001451 int32_t getPid() const { return mInfo.ownerPid; }
1452
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001453 void destroyReceiver() { mInputReceiver = nullptr; }
1454
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001455 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1456
chaviwd1c23182019-12-20 18:44:56 -08001457private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001458 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001459 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001460 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001461 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001462 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001463};
1464
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001465std::atomic<int32_t> FakeWindowHandle::sId{1};
1466
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001467static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001468 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001469 int32_t displayId = ADISPLAY_ID_NONE,
1470 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001471 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001472 bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
1473 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001474 KeyEvent event;
1475 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1476
1477 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001478 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001479 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1480 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001481
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001482 if (!allowKeyRepeat) {
1483 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1484 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001485 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001486 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001487}
1488
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001489static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001490 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001491 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001492}
1493
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001494// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1495// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1496// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001497static InputEventInjectionResult injectKeyDownNoRepeat(
1498 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001499 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001500 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001501 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001502}
1503
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001504static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001505 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001506 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001507}
1508
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001509static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001510 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001511 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001512 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1513 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
1514 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1515 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001516}
1517
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001518static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001519 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001520 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001521 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001522 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1523 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001524 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001525 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
1526 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001527 MotionEventBuilder motionBuilder =
1528 MotionEventBuilder(action, source)
1529 .displayId(displayId)
1530 .eventTime(eventTime)
1531 .rawXCursorPosition(cursorPosition.x)
1532 .rawYCursorPosition(cursorPosition.y)
1533 .pointer(
1534 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1535 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1536 motionBuilder.downTime(eventTime);
1537 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001538
1539 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001540 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1541 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001542}
1543
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001544static InputEventInjectionResult injectMotionDown(
1545 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1546 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001547 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001548}
1549
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001550static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001551 int32_t source, int32_t displayId,
1552 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001553 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001554}
1555
Jackal Guof9696682018-10-05 12:23:23 +08001556static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1557 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1558 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001559 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001560 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1561 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001562
1563 return args;
1564}
1565
Josep del Riob3981622023-04-18 15:49:45 +00001566static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1567 int32_t displayId = ADISPLAY_ID_NONE) {
1568 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1569 // Define a valid key event.
1570 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1571 displayId, 0, action, /* flags */ 0, AKEYCODE_C, KEY_C, AMETA_META_ON,
1572 currentTime);
1573
1574 return args;
1575}
1576
1577static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1578 int32_t displayId = ADISPLAY_ID_NONE) {
1579 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1580 // Define a valid key event.
1581 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1582 displayId, 0, action, /* flags */ 0, AKEYCODE_ASSIST, KEY_ASSISTANT,
1583 AMETA_NONE, currentTime);
1584
1585 return args;
1586}
1587
Prabir Pradhan678438e2023-04-13 19:32:51 +00001588[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1589 int32_t displayId,
1590 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001591 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001592 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1593 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1594 }
1595
chaviwd1c23182019-12-20 18:44:56 -08001596 PointerProperties pointerProperties[pointerCount];
1597 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001598
chaviwd1c23182019-12-20 18:44:56 -08001599 for (size_t i = 0; i < pointerCount; i++) {
1600 pointerProperties[i].clear();
1601 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001602 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001603
chaviwd1c23182019-12-20 18:44:56 -08001604 pointerCoords[i].clear();
1605 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1606 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1607 }
Jackal Guof9696682018-10-05 12:23:23 +08001608
1609 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1610 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001611 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001612 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1613 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001614 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1615 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001616 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1617 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001618
1619 return args;
1620}
1621
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001622static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1623 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1624}
1625
chaviwd1c23182019-12-20 18:44:56 -08001626static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1627 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1628}
1629
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001630static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1631 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001632 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001633}
1634
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001635} // namespace
1636
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001637/**
1638 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1639 * broken channel.
1640 */
1641TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1642 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1643 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001644 sp<FakeWindowHandle>::make(application, mDispatcher,
1645 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001646
1647 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1648
1649 // Window closes its channel, but the window remains.
1650 window->destroyReceiver();
1651 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1652}
1653
Arthur Hungb92218b2018-08-14 12:00:21 +08001654TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001655 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001656 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1657 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001658
Arthur Hung72d8dc32020-03-28 00:48:39 +00001659 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1661 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1662 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001663
1664 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001665 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001666}
1667
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001668TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1669 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001670 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1671 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001672
1673 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1674 // Inject a MotionEvent to an unknown display.
1675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1676 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1677 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1678
1679 // Window should receive motion event.
1680 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1681}
1682
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001683/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001684 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001685 * This test serves as a sanity check for the next test, where setInputWindows is
1686 * called twice.
1687 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001688TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001689 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001690 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1691 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001692 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001693
1694 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001696 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1697 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001698 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001699
1700 // Window should receive motion event.
1701 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1702}
1703
1704/**
1705 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001706 */
1707TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001708 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001709 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1710 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001711 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001712
1713 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1714 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001716 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1717 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001718 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001719
1720 // Window should receive motion event.
1721 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1722}
1723
Arthur Hungb92218b2018-08-14 12:00:21 +08001724// The foreground window should receive the first touch down event.
1725TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001726 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001727 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001728 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001729 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001730 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001731
Arthur Hung72d8dc32020-03-28 00:48:39 +00001732 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1734 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1735 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001736
1737 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001738 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001739 windowSecond->assertNoEvents();
1740}
1741
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001742/**
1743 * Two windows: A top window, and a wallpaper behind the window.
1744 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1745 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001746 * 1. foregroundWindow <-- dup touch to wallpaper
1747 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001748 */
1749TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1750 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1751 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001752 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001753 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001754 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001755 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001756 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001757
1758 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1760 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1761 {100, 200}))
1762 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1763
1764 // Both foreground window and its wallpaper should receive the touch down
1765 foregroundWindow->consumeMotionDown();
1766 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1767
1768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1769 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1770 ADISPLAY_ID_DEFAULT, {110, 200}))
1771 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1772
1773 foregroundWindow->consumeMotionMove();
1774 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1775
1776 // Now the foreground window goes away, but the wallpaper stays
1777 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1778 foregroundWindow->consumeMotionCancel();
1779 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1780 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1781}
1782
1783/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001784 * Two fingers down on the window, and lift off the first finger.
1785 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1786 * contains a single pointer.
1787 */
1788TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1789 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1790 sp<FakeWindowHandle> window =
1791 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1792
1793 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001794 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001795 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1796 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1797 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001798 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001799 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1800 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1801 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1802 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001803 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001804 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1805 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1806 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1807 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001808 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1809 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1810 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1811
1812 // Remove the window. The gesture should be canceled
1813 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
1814 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1815 window->consumeMotionEvent(
1816 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1817}
1818
1819/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001820 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1821 * with the following differences:
1822 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1823 * clean up the connection.
1824 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1825 * Ensure that there's no crash in the dispatcher.
1826 */
1827TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1828 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1829 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001830 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001831 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001832 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001833 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001834 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001835
1836 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1838 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1839 {100, 200}))
1840 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1841
1842 // Both foreground window and its wallpaper should receive the touch down
1843 foregroundWindow->consumeMotionDown();
1844 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1845
1846 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1847 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1848 ADISPLAY_ID_DEFAULT, {110, 200}))
1849 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1850
1851 foregroundWindow->consumeMotionMove();
1852 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1853
1854 // Wallpaper closes its channel, but the window remains.
1855 wallpaperWindow->destroyReceiver();
1856 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1857
1858 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1859 // is no longer valid.
1860 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1861 foregroundWindow->consumeMotionCancel();
1862}
1863
Arthur Hungc539dbb2022-12-08 07:45:36 +00001864class ShouldSplitTouchFixture : public InputDispatcherTest,
1865 public ::testing::WithParamInterface<bool> {};
1866INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1867 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001868/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001869 * A single window that receives touch (on top), and a wallpaper window underneath it.
1870 * The top window gets a multitouch gesture.
1871 * Ensure that wallpaper gets the same gesture.
1872 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001873TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001874 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001875 sp<FakeWindowHandle> foregroundWindow =
1876 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1877 foregroundWindow->setDupTouchToWallpaper(true);
1878 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001879
1880 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001881 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001882 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001883
Arthur Hungc539dbb2022-12-08 07:45:36 +00001884 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001885
1886 // Touch down on top window
1887 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1888 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1889 {100, 100}))
1890 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1891
1892 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001893 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001894 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1895
1896 // Second finger down on the top window
1897 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001898 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001899 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001900 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1901 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001902 .build();
1903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1904 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1905 InputEventInjectionSync::WAIT_FOR_RESULT))
1906 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1907
Harry Cutts33476232023-01-30 19:57:29 +00001908 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1909 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001910 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001911
1912 const MotionEvent secondFingerUpEvent =
1913 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1914 .displayId(ADISPLAY_ID_DEFAULT)
1915 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001916 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1917 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001918 .build();
1919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1920 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
1921 InputEventInjectionSync::WAIT_FOR_RESULT))
1922 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1923 foregroundWindow->consumeMotionPointerUp(0);
1924 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1925
1926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001927 injectMotionEvent(mDispatcher,
1928 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1929 AINPUT_SOURCE_TOUCHSCREEN)
1930 .displayId(ADISPLAY_ID_DEFAULT)
1931 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1932 .pointer(PointerBuilder(/* id */ 1,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001933 ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001934 .x(100)
1935 .y(100))
1936 .build(),
1937 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001938 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1939 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1940 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001941}
1942
1943/**
1944 * Two windows: a window on the left and window on the right.
1945 * A third window, wallpaper, is behind both windows, and spans both top windows.
1946 * The first touch down goes to the left window. A second pointer touches down on the right window.
1947 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1948 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1949 * ACTION_POINTER_DOWN(1).
1950 */
1951TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1952 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1953 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001954 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001955 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001956 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001957
1958 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001959 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001960 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001961 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001962
1963 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001964 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001965 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001966 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001967
1968 mDispatcher->setInputWindows(
1969 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1970
1971 // Touch down on left window
1972 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1973 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1974 {100, 100}))
1975 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1976
1977 // Both foreground window and its wallpaper should receive the touch down
1978 leftWindow->consumeMotionDown();
1979 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1980
1981 // Second finger down on the right window
1982 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001983 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001984 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001985 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1986 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001987 .build();
1988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1989 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1990 InputEventInjectionSync::WAIT_FOR_RESULT))
1991 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1992
1993 leftWindow->consumeMotionMove();
1994 // Since the touch is split, right window gets ACTION_DOWN
1995 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001996 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001997 expectedWallpaperFlags);
1998
1999 // Now, leftWindow, which received the first finger, disappears.
2000 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
2001 leftWindow->consumeMotionCancel();
2002 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2003 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2004
2005 // The pointer that's still down on the right window moves, and goes to the right window only.
2006 // As far as the dispatcher's concerned though, both pointers are still present.
2007 const MotionEvent secondFingerMoveEvent =
2008 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2009 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002010 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2011 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002012 .build();
2013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2014 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2015 InputEventInjectionSync::WAIT_FOR_RESULT));
2016 rightWindow->consumeMotionMove();
2017
2018 leftWindow->assertNoEvents();
2019 rightWindow->assertNoEvents();
2020 wallpaperWindow->assertNoEvents();
2021}
2022
Arthur Hungc539dbb2022-12-08 07:45:36 +00002023/**
2024 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2025 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2026 * The right window should receive ACTION_DOWN.
2027 */
2028TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002029 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002030 sp<FakeWindowHandle> leftWindow =
2031 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2032 leftWindow->setFrame(Rect(0, 0, 200, 200));
2033 leftWindow->setDupTouchToWallpaper(true);
2034 leftWindow->setSlippery(true);
2035
2036 sp<FakeWindowHandle> rightWindow =
2037 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2038 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002039
2040 sp<FakeWindowHandle> wallpaperWindow =
2041 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2042 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002043
Arthur Hungc539dbb2022-12-08 07:45:36 +00002044 mDispatcher->setInputWindows(
2045 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002046
Arthur Hungc539dbb2022-12-08 07:45:36 +00002047 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2049 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002050 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002051 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002052
2053 // Both foreground window and its wallpaper should receive the touch down
2054 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002055 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2056
Arthur Hungc539dbb2022-12-08 07:45:36 +00002057 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002059 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2060 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002061 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2062
Arthur Hungc539dbb2022-12-08 07:45:36 +00002063 leftWindow->consumeMotionCancel();
2064 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2065 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002066}
2067
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002068/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002069 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2070 * interactive, it might stop sending this flag.
2071 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2072 * to have a consistent input stream.
2073 *
2074 * Test procedure:
2075 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2076 * DOWN (new gesture).
2077 *
2078 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2079 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2080 *
2081 * We technically just need a single window here, but we are using two windows (spy on top and a
2082 * regular window below) to emulate the actual situation where it happens on the device.
2083 */
2084TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2085 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2086 sp<FakeWindowHandle> spyWindow =
2087 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2088 spyWindow->setFrame(Rect(0, 0, 200, 200));
2089 spyWindow->setTrustedOverlay(true);
2090 spyWindow->setSpy(true);
2091
2092 sp<FakeWindowHandle> window =
2093 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2094 window->setFrame(Rect(0, 0, 200, 200));
2095
2096 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2097 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002098
2099 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002100 mDispatcher->notifyMotion(
2101 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2102 .deviceId(touchDeviceId)
2103 .policyFlags(DEFAULT_POLICY_FLAGS)
2104 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2105 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002106
Prabir Pradhan678438e2023-04-13 19:32:51 +00002107 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2108 .deviceId(touchDeviceId)
2109 .policyFlags(DEFAULT_POLICY_FLAGS)
2110 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2111 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2112 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002113 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2114 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2115 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2116 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2117
2118 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002119 mDispatcher->notifyMotion(
2120 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2121 .deviceId(touchDeviceId)
2122 .policyFlags(0)
2123 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2124 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2125 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002126 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2127 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2128
2129 // We don't need to reset the device to reproduce the issue, but the reset event typically
2130 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002131 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002132
2133 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002134 mDispatcher->notifyMotion(
2135 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2136 .deviceId(touchDeviceId)
2137 .policyFlags(DEFAULT_POLICY_FLAGS)
2138 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2139 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002140 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2141 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2142
2143 // No more events
2144 spyWindow->assertNoEvents();
2145 window->assertNoEvents();
2146}
2147
2148/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002149 * Two windows: a window on the left and a window on the right.
2150 * Mouse is hovered from the right window into the left window.
2151 * Next, we tap on the left window, where the cursor was last seen.
2152 * The second tap is done onto the right window.
2153 * The mouse and tap are from two different devices.
2154 * We technically don't need to set the downtime / eventtime for these events, but setting these
2155 * explicitly helps during debugging.
2156 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2157 * In the buggy implementation, a tap on the right window would cause a crash.
2158 */
2159TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2160 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2161 sp<FakeWindowHandle> leftWindow =
2162 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2163 leftWindow->setFrame(Rect(0, 0, 200, 200));
2164
2165 sp<FakeWindowHandle> rightWindow =
2166 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2167 rightWindow->setFrame(Rect(200, 0, 400, 200));
2168
2169 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2170 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2171 // stale.
2172 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2173 const int32_t mouseDeviceId = 6;
2174 const int32_t touchDeviceId = 4;
2175 // Move the cursor from right
2176 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2177 injectMotionEvent(mDispatcher,
2178 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2179 AINPUT_SOURCE_MOUSE)
2180 .deviceId(mouseDeviceId)
2181 .downTime(baseTime + 10)
2182 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002183 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002184 .x(300)
2185 .y(100))
2186 .build()));
2187 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2188
2189 // .. to the left window
2190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2191 injectMotionEvent(mDispatcher,
2192 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2193 AINPUT_SOURCE_MOUSE)
2194 .deviceId(mouseDeviceId)
2195 .downTime(baseTime + 10)
2196 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002197 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002198 .x(110)
2199 .y(100))
2200 .build()));
2201 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2202 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2203 // Now tap the left window
2204 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2205 injectMotionEvent(mDispatcher,
2206 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2207 AINPUT_SOURCE_TOUCHSCREEN)
2208 .deviceId(touchDeviceId)
2209 .downTime(baseTime + 40)
2210 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002211 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002212 .x(100)
2213 .y(100))
2214 .build()));
2215 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2216 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2217
2218 // release tap
2219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2220 injectMotionEvent(mDispatcher,
2221 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2222 AINPUT_SOURCE_TOUCHSCREEN)
2223 .deviceId(touchDeviceId)
2224 .downTime(baseTime + 40)
2225 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002226 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002227 .x(100)
2228 .y(100))
2229 .build()));
2230 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2231
2232 // Tap the window on the right
2233 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2234 injectMotionEvent(mDispatcher,
2235 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2236 AINPUT_SOURCE_TOUCHSCREEN)
2237 .deviceId(touchDeviceId)
2238 .downTime(baseTime + 60)
2239 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002240 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002241 .x(300)
2242 .y(100))
2243 .build()));
2244 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2245
2246 // release tap
2247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2248 injectMotionEvent(mDispatcher,
2249 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2250 AINPUT_SOURCE_TOUCHSCREEN)
2251 .deviceId(touchDeviceId)
2252 .downTime(baseTime + 60)
2253 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002254 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002255 .x(300)
2256 .y(100))
2257 .build()));
2258 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2259
2260 // No more events
2261 leftWindow->assertNoEvents();
2262 rightWindow->assertNoEvents();
2263}
2264
2265/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002266 * Start hovering in a window. While this hover is still active, make another window appear on top.
2267 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2268 * While the top window is present, the hovering is stopped.
2269 * Later, hovering gets resumed again.
2270 * Ensure that new hover gesture is handled correctly.
2271 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2272 * to the window that's currently being hovered over.
2273 */
2274TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2275 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2276 sp<FakeWindowHandle> window =
2277 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2278 window->setFrame(Rect(0, 0, 200, 200));
2279
2280 // Only a single window is present at first
2281 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2282
2283 // Start hovering in the window
2284 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2285 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2286 .build());
2287 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2288
2289 // Now, an obscuring window appears!
2290 sp<FakeWindowHandle> obscuringWindow =
2291 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2292 ADISPLAY_ID_DEFAULT,
2293 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2294 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2295 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2296 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2297 obscuringWindow->setNoInputChannel(true);
2298 obscuringWindow->setFocusable(false);
2299 obscuringWindow->setAlpha(1.0);
2300 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2301
2302 // While this new obscuring window is present, the hovering is stopped
2303 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2304 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2305 .build());
2306 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2307
2308 // Now the obscuring window goes away.
2309 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2310
2311 // And a new hover gesture starts.
2312 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2313 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2314 .build());
2315 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2316}
2317
2318/**
2319 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2320 * the obscuring window.
2321 */
2322TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2323 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2324 sp<FakeWindowHandle> window =
2325 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2326 window->setFrame(Rect(0, 0, 200, 200));
2327
2328 // Only a single window is present at first
2329 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2330
2331 // Start hovering in the window
2332 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2333 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2334 .build());
2335 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2336
2337 // Now, an obscuring window appears!
2338 sp<FakeWindowHandle> obscuringWindow =
2339 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2340 ADISPLAY_ID_DEFAULT,
2341 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2342 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2343 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2344 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2345 obscuringWindow->setNoInputChannel(true);
2346 obscuringWindow->setFocusable(false);
2347 obscuringWindow->setAlpha(1.0);
2348 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2349
2350 // While this new obscuring window is present, the hovering continues. The event can't go to the
2351 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2352 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2353 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2354 .build());
2355 obscuringWindow->assertNoEvents();
2356 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2357
2358 // Now the obscuring window goes away.
2359 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2360
2361 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2362 // so it should generate a HOVER_ENTER
2363 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2364 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2365 .build());
2366 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2367
2368 // Now the MOVE should be getting dispatched normally
2369 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2370 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2371 .build());
2372 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2373}
2374
2375/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002376 * Two windows: a window on the left and a window on the right.
2377 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2378 * down. Then, on the left window, also place second touch pointer down.
2379 * This test tries to reproduce a crash.
2380 * In the buggy implementation, second pointer down on the left window would cause a crash.
2381 */
2382TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2383 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2384 sp<FakeWindowHandle> leftWindow =
2385 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2386 leftWindow->setFrame(Rect(0, 0, 200, 200));
2387
2388 sp<FakeWindowHandle> rightWindow =
2389 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2390 rightWindow->setFrame(Rect(200, 0, 400, 200));
2391
2392 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2393
2394 const int32_t touchDeviceId = 4;
2395 const int32_t mouseDeviceId = 6;
2396 NotifyMotionArgs args;
2397
2398 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002399 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2400 .deviceId(mouseDeviceId)
2401 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2402 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002403 leftWindow->consumeMotionEvent(
2404 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2405
2406 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002407 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2408 .deviceId(mouseDeviceId)
2409 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2410 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2411 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002412
2413 leftWindow->consumeMotionEvent(
2414 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2415 leftWindow->consumeMotionEvent(
2416 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2417
Prabir Pradhan678438e2023-04-13 19:32:51 +00002418 mDispatcher->notifyMotion(
2419 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2420 .deviceId(mouseDeviceId)
2421 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2422 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2423 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2424 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002425 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2426
2427 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002428 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2429 .deviceId(touchDeviceId)
2430 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2431 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002432 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2433
2434 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2435
2436 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002437 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2438 .deviceId(touchDeviceId)
2439 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2440 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2441 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002442 leftWindow->consumeMotionEvent(
2443 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2444 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2445 // current implementation.
2446 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2447 rightWindow->consumeMotionEvent(
2448 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2449
2450 leftWindow->assertNoEvents();
2451 rightWindow->assertNoEvents();
2452}
2453
2454/**
2455 * On a single window, use two different devices: mouse and touch.
2456 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2457 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2458 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2459 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2460 * represent a new gesture.
2461 */
2462TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2463 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2464 sp<FakeWindowHandle> window =
2465 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2466 window->setFrame(Rect(0, 0, 400, 400));
2467
2468 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2469
2470 const int32_t touchDeviceId = 4;
2471 const int32_t mouseDeviceId = 6;
2472 NotifyMotionArgs args;
2473
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002474 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002475 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2476 .deviceId(touchDeviceId)
2477 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2478 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002479 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002480 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2481 .deviceId(touchDeviceId)
2482 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2483 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2484 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002485 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002486 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2487 .deviceId(touchDeviceId)
2488 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2489 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2490 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002491 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2492 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2493 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2494
2495 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002496 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2497 .deviceId(mouseDeviceId)
2498 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2499 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2500 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002501
2502 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002503 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002504 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2505
Prabir Pradhan678438e2023-04-13 19:32:51 +00002506 mDispatcher->notifyMotion(
2507 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2508 .deviceId(mouseDeviceId)
2509 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2510 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2511 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2512 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002513 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2514
2515 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002516 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2517 .deviceId(touchDeviceId)
2518 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2519 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2520 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002521 // The pointer_down event should be ignored
2522 window->assertNoEvents();
2523}
2524
2525/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002526 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2527 * the injected event.
2528 */
2529TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2530 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2531 sp<FakeWindowHandle> window =
2532 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2533 window->setFrame(Rect(0, 0, 400, 400));
2534
2535 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2536
2537 const int32_t touchDeviceId = 4;
2538 NotifyMotionArgs args;
2539 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2540 // completion.
2541 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2542 injectMotionEvent(mDispatcher,
2543 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2544 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002545 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002546 .x(50)
2547 .y(50))
2548 .build()));
2549 window->consumeMotionEvent(
2550 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2551
2552 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2553 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002554 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2555 .deviceId(touchDeviceId)
2556 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2557 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002558
2559 window->consumeMotionEvent(
2560 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2561 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2562}
2563
2564/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002565 * This test is similar to the test above, but the sequence of injected events is different.
2566 *
2567 * Two windows: a window on the left and a window on the right.
2568 * Mouse is hovered over the left window.
2569 * Next, we tap on the left window, where the cursor was last seen.
2570 *
2571 * After that, we inject one finger down onto the right window, and then a second finger down onto
2572 * the left window.
2573 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2574 * window (first), and then another on the left window (second).
2575 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2576 * In the buggy implementation, second finger down on the left window would cause a crash.
2577 */
2578TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2579 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2580 sp<FakeWindowHandle> leftWindow =
2581 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2582 leftWindow->setFrame(Rect(0, 0, 200, 200));
2583
2584 sp<FakeWindowHandle> rightWindow =
2585 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2586 rightWindow->setFrame(Rect(200, 0, 400, 200));
2587
2588 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2589
2590 const int32_t mouseDeviceId = 6;
2591 const int32_t touchDeviceId = 4;
2592 // Hover over the left window. Keep the cursor there.
2593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2594 injectMotionEvent(mDispatcher,
2595 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2596 AINPUT_SOURCE_MOUSE)
2597 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002598 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002599 .x(50)
2600 .y(50))
2601 .build()));
2602 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2603
2604 // Tap on left window
2605 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2606 injectMotionEvent(mDispatcher,
2607 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2608 AINPUT_SOURCE_TOUCHSCREEN)
2609 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002610 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002611 .x(100)
2612 .y(100))
2613 .build()));
2614
2615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2616 injectMotionEvent(mDispatcher,
2617 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2618 AINPUT_SOURCE_TOUCHSCREEN)
2619 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002620 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002621 .x(100)
2622 .y(100))
2623 .build()));
2624 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2625 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2626 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2627
2628 // First finger down on right window
2629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2630 injectMotionEvent(mDispatcher,
2631 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2632 AINPUT_SOURCE_TOUCHSCREEN)
2633 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002634 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002635 .x(300)
2636 .y(100))
2637 .build()));
2638 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2639
2640 // Second finger down on the left window
2641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2642 injectMotionEvent(mDispatcher,
2643 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2644 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002645 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002646 .x(300)
2647 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002648 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002649 .x(100)
2650 .y(100))
2651 .build()));
2652 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2653 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2654
2655 // No more events
2656 leftWindow->assertNoEvents();
2657 rightWindow->assertNoEvents();
2658}
2659
2660/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002661 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2662 * While the touch is down, new hover events from the stylus device should be ignored. After the
2663 * touch is gone, stylus hovering should start working again.
2664 */
2665TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2666 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2667 sp<FakeWindowHandle> window =
2668 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2669 window->setFrame(Rect(0, 0, 200, 200));
2670
2671 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2672
2673 const int32_t stylusDeviceId = 5;
2674 const int32_t touchDeviceId = 4;
2675 // Start hovering with stylus
2676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2677 injectMotionEvent(mDispatcher,
2678 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2679 AINPUT_SOURCE_STYLUS)
2680 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002681 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002682 .x(50)
2683 .y(50))
2684 .build()));
2685 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2686
2687 // Finger down on the window
2688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2689 injectMotionEvent(mDispatcher,
2690 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2691 AINPUT_SOURCE_TOUCHSCREEN)
2692 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002693 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002694 .x(100)
2695 .y(100))
2696 .build()));
2697 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2698 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2699
2700 // Try to continue hovering with stylus. Since we are already down, injection should fail
2701 ASSERT_EQ(InputEventInjectionResult::FAILED,
2702 injectMotionEvent(mDispatcher,
2703 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2704 AINPUT_SOURCE_STYLUS)
2705 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002706 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002707 .x(50)
2708 .y(50))
2709 .build()));
2710 // No event should be sent. This event should be ignored because a pointer from another device
2711 // is already down.
2712
2713 // Lift up the finger
2714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2715 injectMotionEvent(mDispatcher,
2716 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2717 AINPUT_SOURCE_TOUCHSCREEN)
2718 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002719 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002720 .x(100)
2721 .y(100))
2722 .build()));
2723 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2724
2725 // Now that the touch is gone, stylus hovering should start working again
2726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2727 injectMotionEvent(mDispatcher,
2728 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2729 AINPUT_SOURCE_STYLUS)
2730 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002731 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002732 .x(50)
2733 .y(50))
2734 .build()));
2735 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2736 // No more events
2737 window->assertNoEvents();
2738}
2739
2740/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002741 * A spy window above a window with no input channel.
2742 * Start hovering with a stylus device, and then tap with it.
2743 * Ensure spy window receives the entire sequence.
2744 */
2745TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2746 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2747 sp<FakeWindowHandle> spyWindow =
2748 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2749 spyWindow->setFrame(Rect(0, 0, 200, 200));
2750 spyWindow->setTrustedOverlay(true);
2751 spyWindow->setSpy(true);
2752 sp<FakeWindowHandle> window =
2753 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2754 window->setNoInputChannel(true);
2755 window->setFrame(Rect(0, 0, 200, 200));
2756
2757 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2758
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002759 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002760 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2761 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2762 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002763 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2764 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002765 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2766 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2767 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002768 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2769
2770 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002771 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2772 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2773 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002774 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2775
2776 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002777 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2778 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2779 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002780 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2781
2782 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002783 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2784 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2785 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002786 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2787 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002788 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2789 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2790 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002791 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2792
2793 // No more events
2794 spyWindow->assertNoEvents();
2795 window->assertNoEvents();
2796}
2797
2798/**
2799 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2800 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2801 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2802 * While the mouse is down, new move events from the touch device should be ignored.
2803 */
2804TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2805 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2806 sp<FakeWindowHandle> spyWindow =
2807 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2808 spyWindow->setFrame(Rect(0, 0, 200, 200));
2809 spyWindow->setTrustedOverlay(true);
2810 spyWindow->setSpy(true);
2811 sp<FakeWindowHandle> window =
2812 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2813 window->setFrame(Rect(0, 0, 200, 200));
2814
2815 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2816
2817 const int32_t mouseDeviceId = 7;
2818 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002819
2820 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002821 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2822 .deviceId(mouseDeviceId)
2823 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2824 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002825 spyWindow->consumeMotionEvent(
2826 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2827 window->consumeMotionEvent(
2828 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2829
2830 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002831 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2832 .deviceId(touchDeviceId)
2833 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2834 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002835 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2836 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2837 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2838 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2839
Prabir Pradhan678438e2023-04-13 19:32:51 +00002840 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2841 .deviceId(touchDeviceId)
2842 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2843 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002844 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2845 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2846
2847 // Pilfer the stream
2848 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2849 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2850
Prabir Pradhan678438e2023-04-13 19:32:51 +00002851 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2852 .deviceId(touchDeviceId)
2853 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2854 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002855 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2856
2857 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002858 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2859 .deviceId(mouseDeviceId)
2860 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2861 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2862 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002863
2864 spyWindow->consumeMotionEvent(
2865 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2866 spyWindow->consumeMotionEvent(
2867 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2868 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2869
Prabir Pradhan678438e2023-04-13 19:32:51 +00002870 mDispatcher->notifyMotion(
2871 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2872 .deviceId(mouseDeviceId)
2873 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2874 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2875 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2876 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002877 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2878 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2879
2880 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002881 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2882 .deviceId(mouseDeviceId)
2883 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2884 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2885 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002886 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2887 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2888
2889 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002890 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2891 .deviceId(touchDeviceId)
2892 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2893 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002894
2895 // No more events
2896 spyWindow->assertNoEvents();
2897 window->assertNoEvents();
2898}
2899
2900/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002901 * On the display, have a single window, and also an area where there's no window.
2902 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2903 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2904 */
2905TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2906 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2907 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002908 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002909
2910 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002911
2912 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002913 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002914
2915 mDispatcher->waitForIdle();
2916 window->assertNoEvents();
2917
2918 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002919 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002920 mDispatcher->waitForIdle();
2921 window->consumeMotionDown();
2922}
2923
2924/**
2925 * Same test as above, but instead of touching the empty space, the first touch goes to
2926 * non-touchable window.
2927 */
2928TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2929 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2930 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002931 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002932 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2933 window1->setTouchable(false);
2934 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002935 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002936 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2937
2938 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2939
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002940 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002941 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002942
2943 mDispatcher->waitForIdle();
2944 window1->assertNoEvents();
2945 window2->assertNoEvents();
2946
2947 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002948 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002949 mDispatcher->waitForIdle();
2950 window2->consumeMotionDown();
2951}
2952
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002953/**
2954 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2955 * to the event time of the first ACTION_DOWN sent to the particular window.
2956 */
2957TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2958 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2959 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002960 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002961 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2962 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002963 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002964 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2965
2966 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2967
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002968 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002969 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002970
2971 mDispatcher->waitForIdle();
2972 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002973 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002974 window2->assertNoEvents();
2975 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
2976 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
2977 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
2978
2979 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002980 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002981 mDispatcher->waitForIdle();
2982 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002983 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002984 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
2985 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
2986 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
2987 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
2988
2989 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002990 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002991 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002992 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002993
2994 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002995 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002996 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002997 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002998
2999 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3000 window1->consumeMotionMove();
3001 window1->assertNoEvents();
3002
3003 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003004 mDispatcher->notifyMotion(
3005 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003006 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003007 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003008
Prabir Pradhan678438e2023-04-13 19:32:51 +00003009 mDispatcher->notifyMotion(
3010 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003011 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003012 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003013}
3014
Garfield Tandf26e862020-07-01 20:18:19 -07003015TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003016 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003017 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003018 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003019 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003020 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003021 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003022 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003023
3024 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3025
3026 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3027
3028 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003030 injectMotionEvent(mDispatcher,
3031 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3032 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003033 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003034 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003035 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003036
3037 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003039 injectMotionEvent(mDispatcher,
3040 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3041 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003042 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003043 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003044 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3045 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003046
3047 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003049 injectMotionEvent(mDispatcher,
3050 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3051 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003052 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003053 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003054 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3055 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003056
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003058 injectMotionEvent(mDispatcher,
3059 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3060 AINPUT_SOURCE_MOUSE)
3061 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3062 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003063 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003064 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003065 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003066
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003068 injectMotionEvent(mDispatcher,
3069 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3070 AINPUT_SOURCE_MOUSE)
3071 .buttonState(0)
3072 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003073 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003074 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003075 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003076
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003078 injectMotionEvent(mDispatcher,
3079 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3080 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003081 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003082 .build()));
3083 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3084
3085 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003086 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003087 injectMotionEvent(mDispatcher,
3088 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3089 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003090 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003091 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003092 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003093
3094 // No more events
3095 windowLeft->assertNoEvents();
3096 windowRight->assertNoEvents();
3097}
3098
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003099/**
3100 * Put two fingers down (and don't release them) and click the mouse button.
3101 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3102 * currently active gesture should be canceled, and the new one should proceed.
3103 */
3104TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3105 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3106 sp<FakeWindowHandle> window =
3107 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3108 window->setFrame(Rect(0, 0, 600, 800));
3109
3110 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3111
3112 const int32_t touchDeviceId = 4;
3113 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003114
3115 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003116 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3117 .deviceId(touchDeviceId)
3118 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3119 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003120
Prabir Pradhan678438e2023-04-13 19:32:51 +00003121 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3122 .deviceId(touchDeviceId)
3123 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3124 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3125 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003126 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3127 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3128
3129 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003130 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3131 .deviceId(mouseDeviceId)
3132 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3133 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3134 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003135 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3136 WithPointerCount(2u)));
3137 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3138
Prabir Pradhan678438e2023-04-13 19:32:51 +00003139 mDispatcher->notifyMotion(
3140 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3141 .deviceId(mouseDeviceId)
3142 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3143 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3144 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3145 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003146 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3147
3148 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3149 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003150 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3151 .deviceId(touchDeviceId)
3152 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3153 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3154 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003155 window->assertNoEvents();
3156}
3157
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003158TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3159 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3160
3161 sp<FakeWindowHandle> spyWindow =
3162 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3163 spyWindow->setFrame(Rect(0, 0, 600, 800));
3164 spyWindow->setTrustedOverlay(true);
3165 spyWindow->setSpy(true);
3166 sp<FakeWindowHandle> window =
3167 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3168 window->setFrame(Rect(0, 0, 600, 800));
3169
3170 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3171 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3172
3173 // Send mouse cursor to the window
3174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3175 injectMotionEvent(mDispatcher,
3176 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3177 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003178 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003179 .x(100)
3180 .y(100))
3181 .build()));
3182
3183 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3184 WithSource(AINPUT_SOURCE_MOUSE)));
3185 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3186 WithSource(AINPUT_SOURCE_MOUSE)));
3187
3188 window->assertNoEvents();
3189 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003190}
3191
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003192TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3193 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3194
3195 sp<FakeWindowHandle> spyWindow =
3196 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3197 spyWindow->setFrame(Rect(0, 0, 600, 800));
3198 spyWindow->setTrustedOverlay(true);
3199 spyWindow->setSpy(true);
3200 sp<FakeWindowHandle> window =
3201 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3202 window->setFrame(Rect(0, 0, 600, 800));
3203
3204 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3205 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3206
3207 // Send mouse cursor to the window
3208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3209 injectMotionEvent(mDispatcher,
3210 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3211 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003212 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003213 .x(100)
3214 .y(100))
3215 .build()));
3216
3217 // Move mouse cursor
3218 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3219 injectMotionEvent(mDispatcher,
3220 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3221 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003222 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003223 .x(110)
3224 .y(110))
3225 .build()));
3226
3227 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3228 WithSource(AINPUT_SOURCE_MOUSE)));
3229 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3230 WithSource(AINPUT_SOURCE_MOUSE)));
3231 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3232 WithSource(AINPUT_SOURCE_MOUSE)));
3233 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3234 WithSource(AINPUT_SOURCE_MOUSE)));
3235 // Touch down on the window
3236 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3237 injectMotionEvent(mDispatcher,
3238 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3239 AINPUT_SOURCE_TOUCHSCREEN)
3240 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003241 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003242 .x(200)
3243 .y(200))
3244 .build()));
3245 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3246 WithSource(AINPUT_SOURCE_MOUSE)));
3247 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3248 WithSource(AINPUT_SOURCE_MOUSE)));
3249 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3250 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3251 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3252 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3253
3254 // pilfer the motion, retaining the gesture on the spy window.
3255 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3256 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3257 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3258
3259 // Touch UP on the window
3260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3261 injectMotionEvent(mDispatcher,
3262 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3263 AINPUT_SOURCE_TOUCHSCREEN)
3264 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003265 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003266 .x(200)
3267 .y(200))
3268 .build()));
3269 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3270 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3271
3272 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3273 // to send a new gesture. It should again go to both windows (spy and the window below), just
3274 // like the first gesture did, before pilfering. The window configuration has not changed.
3275
3276 // One more tap - DOWN
3277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3278 injectMotionEvent(mDispatcher,
3279 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3280 AINPUT_SOURCE_TOUCHSCREEN)
3281 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003282 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003283 .x(250)
3284 .y(250))
3285 .build()));
3286 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3287 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3288 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3289 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3290
3291 // Touch UP on the window
3292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3293 injectMotionEvent(mDispatcher,
3294 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3295 AINPUT_SOURCE_TOUCHSCREEN)
3296 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003297 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003298 .x(250)
3299 .y(250))
3300 .build()));
3301 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3302 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3303 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3304 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3305
3306 window->assertNoEvents();
3307 spyWindow->assertNoEvents();
3308}
3309
Garfield Tandf26e862020-07-01 20:18:19 -07003310// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3311// directly in this test.
3312TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003313 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003314 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003315 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003316 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003317
3318 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3319
3320 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3321
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003322 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003323 injectMotionEvent(mDispatcher,
3324 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3325 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003326 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003327 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003328 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003329 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003331 injectMotionEvent(mDispatcher,
3332 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3333 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003334 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003335 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003336 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3337 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003338
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003339 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003340 injectMotionEvent(mDispatcher,
3341 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3342 AINPUT_SOURCE_MOUSE)
3343 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3344 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003345 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003346 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003347 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003348
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003349 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003350 injectMotionEvent(mDispatcher,
3351 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3352 AINPUT_SOURCE_MOUSE)
3353 .buttonState(0)
3354 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003355 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003356 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003357 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003358
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003360 injectMotionEvent(mDispatcher,
3361 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3362 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003363 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003364 .build()));
3365 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3366
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003367 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3368 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3369 ASSERT_EQ(InputEventInjectionResult::FAILED,
Garfield Tandf26e862020-07-01 20:18:19 -07003370 injectMotionEvent(mDispatcher,
3371 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3372 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003373 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003374 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003375 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003376}
3377
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003378/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003379 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3380 * is generated.
3381 */
3382TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3383 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3384 sp<FakeWindowHandle> window =
3385 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3386 window->setFrame(Rect(0, 0, 1200, 800));
3387
3388 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3389
3390 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3391
3392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3393 injectMotionEvent(mDispatcher,
3394 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3395 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003396 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003397 .x(300)
3398 .y(400))
3399 .build()));
3400 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3401
3402 // Remove the window, but keep the channel.
3403 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3404 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3405}
3406
3407/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003408 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3409 */
3410TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3411 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3412 sp<FakeWindowHandle> window =
3413 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3414 window->setFrame(Rect(0, 0, 100, 100));
3415
3416 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3417
3418 const int32_t mouseDeviceId = 7;
3419 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003420
3421 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003422 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3423 .deviceId(mouseDeviceId)
3424 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3425 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003426 window->consumeMotionEvent(
3427 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3428
3429 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003430 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3431 .deviceId(touchDeviceId)
3432 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3433 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003434
3435 window->consumeMotionEvent(
3436 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3437 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3438}
3439
3440/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003441 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003442 * The tap causes a HOVER_EXIT event to be generated because the current event
3443 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003444 */
3445TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3446 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3447 sp<FakeWindowHandle> window =
3448 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3449 window->setFrame(Rect(0, 0, 100, 100));
3450
3451 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3452
3453 // Inject a hover_move from mouse.
3454 NotifyMotionArgs motionArgs =
3455 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3456 ADISPLAY_ID_DEFAULT, {{50, 50}});
3457 motionArgs.xCursorPosition = 50;
3458 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003459 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003460 ASSERT_NO_FATAL_FAILURE(
3461 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3462 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003463
3464 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003465 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3466 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3467 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003468 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003469 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3470 WithSource(AINPUT_SOURCE_MOUSE))));
3471
3472 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003473 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3474 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3475
Prabir Pradhan678438e2023-04-13 19:32:51 +00003476 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3477 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003478 ASSERT_NO_FATAL_FAILURE(
3479 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3480 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3481}
3482
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003483TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3484 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3485 sp<FakeWindowHandle> windowDefaultDisplay =
3486 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3487 ADISPLAY_ID_DEFAULT);
3488 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3489 sp<FakeWindowHandle> windowSecondDisplay =
3490 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3491 SECOND_DISPLAY_ID);
3492 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3493
3494 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3495 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3496
3497 // Set cursor position in window in default display and check that hover enter and move
3498 // events are generated.
3499 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3500 injectMotionEvent(mDispatcher,
3501 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3502 AINPUT_SOURCE_MOUSE)
3503 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003504 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003505 .x(300)
3506 .y(600))
3507 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003508 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003509
3510 // Remove all windows in secondary display and check that no event happens on window in
3511 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003512 mDispatcher->setInputWindows(
3513 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003514 windowDefaultDisplay->assertNoEvents();
3515
3516 // Move cursor position in window in default display and check that only hover move
3517 // event is generated and not hover enter event.
3518 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3519 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3520 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3521 injectMotionEvent(mDispatcher,
3522 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3523 AINPUT_SOURCE_MOUSE)
3524 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003525 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003526 .x(400)
3527 .y(700))
3528 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003529 windowDefaultDisplay->consumeMotionEvent(
3530 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3531 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003532 windowDefaultDisplay->assertNoEvents();
3533}
3534
Garfield Tan00f511d2019-06-12 16:55:40 -07003535TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003536 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003537
3538 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003539 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003540 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003541 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003542 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003543 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003544
3545 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3546
Arthur Hung72d8dc32020-03-28 00:48:39 +00003547 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003548
3549 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3550 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003551 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003552 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003553 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003554 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003555 windowRight->assertNoEvents();
3556}
3557
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003558TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003559 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003560 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3561 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003562 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003563
Arthur Hung72d8dc32020-03-28 00:48:39 +00003564 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003565 setFocusedWindow(window);
3566
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003567 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003568
Prabir Pradhan678438e2023-04-13 19:32:51 +00003569 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003570
3571 // Window should receive key down event.
3572 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3573
3574 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3575 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003576 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003577 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003578 AKEY_EVENT_FLAG_CANCELED);
3579}
3580
3581TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003582 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003583 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3584 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003585
Arthur Hung72d8dc32020-03-28 00:48:39 +00003586 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003587
Prabir Pradhan678438e2023-04-13 19:32:51 +00003588 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3589 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003590
3591 // Window should receive motion down event.
3592 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3593
3594 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3595 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003596 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003597 window->consumeMotionEvent(
3598 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003599}
3600
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003601TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3602 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3603 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3604 "Fake Window", ADISPLAY_ID_DEFAULT);
3605
3606 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3607
3608 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3609 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3610 .build());
3611
3612 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3613
3614 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3615 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3616 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3617
3618 // After the device has been reset, a new hovering stream can be sent to the window
3619 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3620 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3621 .build());
3622 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3623}
3624
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003625TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003627 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3628 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003629 window->setFocusable(true);
3630
3631 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3632 setFocusedWindow(window);
3633
3634 window->consumeFocusEvent(true);
3635
Prabir Pradhan678438e2023-04-13 19:32:51 +00003636 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003637 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3638 const nsecs_t injectTime = keyArgs.eventTime;
3639 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003640 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003641 // The dispatching time should be always greater than or equal to intercept key timeout.
3642 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3643 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3644 std::chrono::nanoseconds(interceptKeyTimeout).count());
3645}
3646
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003647/**
3648 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
3649 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003650TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3651 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003652 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3653 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003654 window->setFocusable(true);
3655
3656 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3657 setFocusedWindow(window);
3658
3659 window->consumeFocusEvent(true);
3660
Prabir Pradhan678438e2023-04-13 19:32:51 +00003661 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003662 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003663
3664 // Set a value that's significantly larger than the default consumption timeout. If the
3665 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
3666 mFakePolicy->setInterceptKeyTimeout(600ms);
3667 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
3668 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003669 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3670}
3671
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003672/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003673 * Two windows. First is a regular window. Second does not overlap with the first, and has
3674 * WATCH_OUTSIDE_TOUCH.
3675 * Both windows are owned by the same UID.
3676 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3677 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3678 */
3679TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3680 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3681 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3682 "First Window", ADISPLAY_ID_DEFAULT);
3683 window->setFrame(Rect{0, 0, 100, 100});
3684
3685 sp<FakeWindowHandle> outsideWindow =
3686 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3687 ADISPLAY_ID_DEFAULT);
3688 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3689 outsideWindow->setWatchOutsideTouch(true);
3690 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3691 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3692
3693 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003694 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3695 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3696 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003697 window->consumeMotionDown();
3698 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3699 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3700 outsideWindow->consumeMotionEvent(
3701 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3702}
3703
3704/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003705 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3706 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3707 * ACTION_OUTSIDE event is sent per gesture.
3708 */
3709TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3710 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3711 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003712 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3713 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003714 window->setWatchOutsideTouch(true);
3715 window->setFrame(Rect{0, 0, 100, 100});
3716 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003717 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3718 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003719 secondWindow->setFrame(Rect{100, 100, 200, 200});
3720 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003721 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3722 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003723 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3724 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3725
3726 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003727 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3728 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3729 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003730 window->assertNoEvents();
3731 secondWindow->assertNoEvents();
3732
3733 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3734 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003735 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3736 ADISPLAY_ID_DEFAULT,
3737 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003738 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3739 window->consumeMotionEvent(
3740 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003741 secondWindow->consumeMotionDown();
3742 thirdWindow->assertNoEvents();
3743
3744 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3745 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003746 mDispatcher->notifyMotion(
3747 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3748 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003749 window->assertNoEvents();
3750 secondWindow->consumeMotionMove();
3751 thirdWindow->consumeMotionDown();
3752}
3753
Prabir Pradhan814fe082022-07-22 20:22:18 +00003754TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3755 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003756 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3757 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003758 window->setFocusable(true);
3759
Patrick Williamsd828f302023-04-28 17:52:08 -05003760 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003761 setFocusedWindow(window);
3762
3763 window->consumeFocusEvent(true);
3764
Prabir Pradhan678438e2023-04-13 19:32:51 +00003765 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3766 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3767 mDispatcher->notifyKey(keyDown);
3768 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003769
3770 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3771 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3772
3773 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05003774 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003775
3776 window->consumeFocusEvent(false);
3777
Prabir Pradhan678438e2023-04-13 19:32:51 +00003778 mDispatcher->notifyKey(keyDown);
3779 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003780 window->assertNoEvents();
3781}
3782
Arthur Hung96483742022-11-15 03:30:48 +00003783TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3784 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3785 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3786 "Fake Window", ADISPLAY_ID_DEFAULT);
3787 // Ensure window is non-split and have some transform.
3788 window->setPreventSplitting(true);
3789 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05003790 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003791
3792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3793 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3794 {50, 50}))
3795 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3796 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3797
3798 const MotionEvent secondFingerDownEvent =
3799 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3800 .displayId(ADISPLAY_ID_DEFAULT)
3801 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003802 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3803 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003804 .build();
3805 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3806 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3807 InputEventInjectionSync::WAIT_FOR_RESULT))
3808 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3809
3810 const MotionEvent* event = window->consumeMotion();
3811 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3812 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3813 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3814 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3815 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3816}
3817
Harry Cuttsb166c002023-05-09 13:06:05 +00003818TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
3819 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3820 sp<FakeWindowHandle> window =
3821 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3822 window->setFrame(Rect(0, 0, 400, 400));
3823 sp<FakeWindowHandle> trustedOverlay =
3824 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
3825 ADISPLAY_ID_DEFAULT);
3826 trustedOverlay->setSpy(true);
3827 trustedOverlay->setTrustedOverlay(true);
3828
3829 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {trustedOverlay, window}}});
3830
3831 // Start a three-finger touchpad swipe
3832 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3833 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3834 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3835 .build());
3836 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3837 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3838 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3839 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3840 .build());
3841 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3842 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3843 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3844 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3845 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3846 .build());
3847
3848 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3849 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3850 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
3851
3852 // Move the swipe a bit
3853 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3854 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3855 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3856 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3857 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3858 .build());
3859
3860 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3861
3862 // End the swipe
3863 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3864 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3865 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3866 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3867 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3868 .build());
3869 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3870 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3871 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3872 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3873 .build());
3874 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3875 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3876 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3877 .build());
3878
3879 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
3880 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3881 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
3882
3883 window->assertNoEvents();
3884}
3885
3886TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
3887 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3888 sp<FakeWindowHandle> window =
3889 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3890 window->setFrame(Rect(0, 0, 400, 400));
3891 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3892
3893 // Start a three-finger touchpad swipe
3894 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3895 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3896 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3897 .build());
3898 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3899 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3900 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3901 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3902 .build());
3903 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3904 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3905 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3906 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3907 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3908 .build());
3909
3910 // Move the swipe a bit
3911 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3912 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3913 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3914 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3915 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3916 .build());
3917
3918 // End the swipe
3919 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3920 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3921 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3922 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3923 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3924 .build());
3925 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3926 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3927 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3928 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3929 .build());
3930 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3931 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3932 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3933 .build());
3934
3935 window->assertNoEvents();
3936}
3937
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003938/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003939 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
3940 * the first pointer.
3941 * Ensure that the second pointer is not sent to the window.
3942 *
3943 * The subsequent gesture should be correctly delivered to the window.
3944 */
3945TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
3946 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3947 sp<FakeWindowHandle> window =
3948 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3949 window->setFrame(Rect(0, 0, 400, 400));
3950 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3951
3952 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
3953 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3954 .downTime(baseTime + 10)
3955 .eventTime(baseTime + 10)
3956 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3957 .build());
3958
3959 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3960
3961 // We need a new window object for the same window, because dispatcher will store objects by
3962 // reference. That means that the testing code and the dispatcher will refer to the same shared
3963 // object. Calling window->setTransform here would affect dispatcher's comparison
3964 // of the old window to the new window, since both the old window and the new window would be
3965 // updated to the same value.
3966 sp<FakeWindowHandle> windowDup = window->duplicate();
3967
3968 // Change the transform so that the orientation is now different from original.
3969 windowDup->setWindowTransform(0, -1, 1, 0);
3970
3971 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDup}}});
3972
3973 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3974
3975 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3976 .downTime(baseTime + 10)
3977 .eventTime(baseTime + 30)
3978 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3979 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3980 .build());
3981
3982 // Finish the gesture and start a new one. Ensure the new gesture is sent to the window
3983 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
3984 .downTime(baseTime + 10)
3985 .eventTime(baseTime + 40)
3986 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3987 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3988 .build());
3989 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3990 .downTime(baseTime + 10)
3991 .eventTime(baseTime + 50)
3992 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3993 .build());
3994
3995 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3996 .downTime(baseTime + 60)
3997 .eventTime(baseTime + 60)
3998 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
3999 .build());
4000
4001 windowDup->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4002}
4003
4004/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004005 * Ensure the correct coordinate spaces are used by InputDispatcher.
4006 *
4007 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4008 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4009 * space.
4010 */
4011class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4012public:
4013 void SetUp() override {
4014 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004015 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004016 }
4017
4018 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4019 gui::DisplayInfo info;
4020 info.displayId = displayId;
4021 info.transform = transform;
4022 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004023 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004024 }
4025
4026 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4027 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004028 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004029 }
4030
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004031 void removeAllWindowsAndDisplays() {
4032 mDisplayInfos.clear();
4033 mWindowInfos.clear();
4034 }
4035
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004036 // Set up a test scenario where the display has a scaled projection and there are two windows
4037 // on the display.
4038 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4039 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4040 // respectively.
4041 ui::Transform displayTransform;
4042 displayTransform.set(2, 0, 0, 4);
4043 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4044
4045 std::shared_ptr<FakeApplicationHandle> application =
4046 std::make_shared<FakeApplicationHandle>();
4047
4048 // Add two windows to the display. Their frames are represented in the display space.
4049 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004050 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4051 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004052 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4053 addWindow(firstWindow);
4054
4055 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004056 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4057 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004058 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4059 addWindow(secondWindow);
4060 return {std::move(firstWindow), std::move(secondWindow)};
4061 }
4062
4063private:
4064 std::vector<gui::DisplayInfo> mDisplayInfos;
4065 std::vector<gui::WindowInfo> mWindowInfos;
4066};
4067
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004068TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004069 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4070 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004071 // selected so that if the hit test was performed with the point and the bounds being in
4072 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004073 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4074 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4075 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004076
4077 firstWindow->consumeMotionDown();
4078 secondWindow->assertNoEvents();
4079}
4080
4081// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4082// the event should be treated as being in the logical display space.
4083TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4084 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4085 // Send down to the first window. The point is represented in the logical display space. The
4086 // point is selected so that if the hit test was done in logical display space, then it would
4087 // end up in the incorrect window.
4088 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4089 PointF{75 * 2, 55 * 4});
4090
4091 firstWindow->consumeMotionDown();
4092 secondWindow->assertNoEvents();
4093}
4094
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004095// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4096// event should be treated as being in the logical display space.
4097TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4098 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4099
4100 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4101 ui::Transform injectedEventTransform;
4102 injectedEventTransform.set(matrix);
4103 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4104 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4105
4106 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4107 .displayId(ADISPLAY_ID_DEFAULT)
4108 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004109 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004110 .x(untransformedPoint.x)
4111 .y(untransformedPoint.y))
4112 .build();
4113 event.transform(matrix);
4114
4115 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
4116 InputEventInjectionSync::WAIT_FOR_RESULT);
4117
4118 firstWindow->consumeMotionDown();
4119 secondWindow->assertNoEvents();
4120}
4121
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004122TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4123 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4124
4125 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004126 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4127 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4128 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004129
4130 firstWindow->assertNoEvents();
4131 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004132 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004133 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4134
4135 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4136 EXPECT_EQ(300, event->getRawX(0));
4137 EXPECT_EQ(880, event->getRawY(0));
4138
4139 // Ensure that the x and y values are in the window's coordinate space.
4140 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4141 // the logical display space. This will be the origin of the window space.
4142 EXPECT_EQ(100, event->getX(0));
4143 EXPECT_EQ(80, event->getY(0));
4144}
4145
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004146/** Ensure consistent behavior of InputDispatcher in all orientations. */
4147class InputDispatcherDisplayOrientationFixture
4148 : public InputDispatcherDisplayProjectionTest,
4149 public ::testing::WithParamInterface<ui::Rotation> {};
4150
4151// This test verifies the touchable region of a window for all rotations of the display by tapping
4152// in different locations on the display, specifically points close to the four corners of a
4153// window.
4154TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4155 constexpr static int32_t displayWidth = 400;
4156 constexpr static int32_t displayHeight = 800;
4157
4158 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4159
4160 const auto rotation = GetParam();
4161
4162 // Set up the display with the specified rotation.
4163 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4164 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4165 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4166 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4167 logicalDisplayWidth, logicalDisplayHeight);
4168 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4169
4170 // Create a window with its bounds determined in the logical display.
4171 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4172 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4173 sp<FakeWindowHandle> window =
4174 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4175 window->setFrame(frameInDisplay, displayTransform);
4176 addWindow(window);
4177
4178 // The following points in logical display space should be inside the window.
4179 static const std::array<vec2, 4> insidePoints{
4180 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4181 for (const auto pointInsideWindow : insidePoints) {
4182 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4183 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004184 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4185 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4186 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004187 window->consumeMotionDown();
4188
Prabir Pradhan678438e2023-04-13 19:32:51 +00004189 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4190 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4191 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004192 window->consumeMotionUp();
4193 }
4194
4195 // The following points in logical display space should be outside the window.
4196 static const std::array<vec2, 5> outsidePoints{
4197 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4198 for (const auto pointOutsideWindow : outsidePoints) {
4199 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4200 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004201 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4202 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4203 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004204
Prabir Pradhan678438e2023-04-13 19:32:51 +00004205 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4206 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4207 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004208 }
4209 window->assertNoEvents();
4210}
4211
4212// Run the precision tests for all rotations.
4213INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4214 InputDispatcherDisplayOrientationFixture,
4215 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4216 ui::ROTATION_270),
4217 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4218 return ftl::enum_string(testParamInfo.param);
4219 });
4220
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004221using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4222 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004223
4224class TransferTouchFixture : public InputDispatcherTest,
4225 public ::testing::WithParamInterface<TransferFunction> {};
4226
4227TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004228 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004229
4230 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004231 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004232 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4233 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004234 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004235 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004236 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4237 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004238 sp<FakeWindowHandle> wallpaper =
4239 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4240 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004241 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004242 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004243
4244 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004245 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4246 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004247
Svet Ganov5d3bc372020-01-26 23:11:07 -08004248 // Only the first window should get the down event
4249 firstWindow->consumeMotionDown();
4250 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004251 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004252
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004253 // Transfer touch to the second window
4254 TransferFunction f = GetParam();
4255 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4256 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004257 // The first window gets cancel and the second gets down
4258 firstWindow->consumeMotionCancel();
4259 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004260 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004261
4262 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004263 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4264 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004265 // The first window gets no events and the second gets up
4266 firstWindow->assertNoEvents();
4267 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004268 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004269}
4270
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004271/**
4272 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4273 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4274 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4275 * natural to the user.
4276 * In this test, we are sending a pointer to both spy window and first window. We then try to
4277 * transfer touch to the second window. The dispatcher should identify the first window as the
4278 * one that should lose the gesture, and therefore the action should be to move the gesture from
4279 * the first window to the second.
4280 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4281 * the other API, as well.
4282 */
4283TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4284 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4285
4286 // Create a couple of windows + a spy window
4287 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004288 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004289 spyWindow->setTrustedOverlay(true);
4290 spyWindow->setSpy(true);
4291 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004292 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004293 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004294 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004295
4296 // Add the windows to the dispatcher
4297 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4298
4299 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004300 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4301 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004302 // Only the first window and spy should get the down event
4303 spyWindow->consumeMotionDown();
4304 firstWindow->consumeMotionDown();
4305
4306 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4307 // if f === 'transferTouch'.
4308 TransferFunction f = GetParam();
4309 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4310 ASSERT_TRUE(success);
4311 // The first window gets cancel and the second gets down
4312 firstWindow->consumeMotionCancel();
4313 secondWindow->consumeMotionDown();
4314
4315 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004316 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4317 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004318 // The first window gets no events and the second+spy get up
4319 firstWindow->assertNoEvents();
4320 spyWindow->consumeMotionUp();
4321 secondWindow->consumeMotionUp();
4322}
4323
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004324TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004325 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004326
4327 PointF touchPoint = {10, 10};
4328
4329 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004330 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004331 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4332 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004333 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004334 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004335 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4336 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004337 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004338
4339 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004340 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004341
4342 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004343 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4344 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4345 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004346 // Only the first window should get the down event
4347 firstWindow->consumeMotionDown();
4348 secondWindow->assertNoEvents();
4349
4350 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004351 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4352 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004353 // Only the first window should get the pointer down event
4354 firstWindow->consumeMotionPointerDown(1);
4355 secondWindow->assertNoEvents();
4356
4357 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004358 TransferFunction f = GetParam();
4359 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4360 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004361 // The first window gets cancel and the second gets down and pointer down
4362 firstWindow->consumeMotionCancel();
4363 secondWindow->consumeMotionDown();
4364 secondWindow->consumeMotionPointerDown(1);
4365
4366 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004367 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4368 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004369 // The first window gets nothing and the second gets pointer up
4370 firstWindow->assertNoEvents();
4371 secondWindow->consumeMotionPointerUp(1);
4372
4373 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004374 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4375 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004376 // The first window gets nothing and the second gets up
4377 firstWindow->assertNoEvents();
4378 secondWindow->consumeMotionUp();
4379}
4380
Arthur Hungc539dbb2022-12-08 07:45:36 +00004381TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4382 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4383
4384 // Create a couple of windows
4385 sp<FakeWindowHandle> firstWindow =
4386 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4387 ADISPLAY_ID_DEFAULT);
4388 firstWindow->setDupTouchToWallpaper(true);
4389 sp<FakeWindowHandle> secondWindow =
4390 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4391 ADISPLAY_ID_DEFAULT);
4392 secondWindow->setDupTouchToWallpaper(true);
4393
4394 sp<FakeWindowHandle> wallpaper1 =
4395 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4396 wallpaper1->setIsWallpaper(true);
4397
4398 sp<FakeWindowHandle> wallpaper2 =
4399 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4400 wallpaper2->setIsWallpaper(true);
4401 // Add the windows to the dispatcher
4402 mDispatcher->setInputWindows(
4403 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4404
4405 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004406 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4407 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004408
4409 // Only the first window should get the down event
4410 firstWindow->consumeMotionDown();
4411 secondWindow->assertNoEvents();
4412 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4413 wallpaper2->assertNoEvents();
4414
4415 // Transfer touch focus to the second window
4416 TransferFunction f = GetParam();
4417 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4418 ASSERT_TRUE(success);
4419
4420 // The first window gets cancel and the second gets down
4421 firstWindow->consumeMotionCancel();
4422 secondWindow->consumeMotionDown();
4423 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4424 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4425
4426 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004427 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4428 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004429 // The first window gets no events and the second gets up
4430 firstWindow->assertNoEvents();
4431 secondWindow->consumeMotionUp();
4432 wallpaper1->assertNoEvents();
4433 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4434}
4435
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004436// For the cases of single pointer touch and two pointers non-split touch, the api's
4437// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4438// for the case where there are multiple pointers split across several windows.
4439INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4440 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004441 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4442 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004443 return dispatcher->transferTouch(destChannelToken,
4444 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004445 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004446 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4447 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004448 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004449 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004450 }));
4451
Svet Ganov5d3bc372020-01-26 23:11:07 -08004452TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004453 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004454
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004455 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004456 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4457 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004458 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004459
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004460 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004461 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4462 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004463 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004464
4465 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004466 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004467
4468 PointF pointInFirst = {300, 200};
4469 PointF pointInSecond = {300, 600};
4470
4471 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004472 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4473 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4474 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004475 // Only the first window should get the down event
4476 firstWindow->consumeMotionDown();
4477 secondWindow->assertNoEvents();
4478
4479 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004480 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4481 ADISPLAY_ID_DEFAULT,
4482 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004483 // The first window gets a move and the second a down
4484 firstWindow->consumeMotionMove();
4485 secondWindow->consumeMotionDown();
4486
4487 // Transfer touch focus to the second window
4488 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4489 // The first window gets cancel and the new gets pointer down (it already saw down)
4490 firstWindow->consumeMotionCancel();
4491 secondWindow->consumeMotionPointerDown(1);
4492
4493 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004494 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4495 ADISPLAY_ID_DEFAULT,
4496 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004497 // The first window gets nothing and the second gets pointer up
4498 firstWindow->assertNoEvents();
4499 secondWindow->consumeMotionPointerUp(1);
4500
4501 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004502 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4503 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004504 // The first window gets nothing and the second gets up
4505 firstWindow->assertNoEvents();
4506 secondWindow->consumeMotionUp();
4507}
4508
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004509// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4510// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4511// touch is not supported, so the touch should continue on those windows and the transferred-to
4512// window should get nothing.
4513TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4514 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4515
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004516 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004517 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4518 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004519 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004520
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004521 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004522 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4523 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004524 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004525
4526 // Add the windows to the dispatcher
4527 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4528
4529 PointF pointInFirst = {300, 200};
4530 PointF pointInSecond = {300, 600};
4531
4532 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004533 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4534 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4535 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004536 // Only the first window should get the down event
4537 firstWindow->consumeMotionDown();
4538 secondWindow->assertNoEvents();
4539
4540 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004541 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4542 ADISPLAY_ID_DEFAULT,
4543 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004544 // The first window gets a move and the second a down
4545 firstWindow->consumeMotionMove();
4546 secondWindow->consumeMotionDown();
4547
4548 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004549 const bool transferred =
4550 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004551 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4552 ASSERT_FALSE(transferred);
4553 firstWindow->assertNoEvents();
4554 secondWindow->assertNoEvents();
4555
4556 // The rest of the dispatch should proceed as normal
4557 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004558 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4559 ADISPLAY_ID_DEFAULT,
4560 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004561 // The first window gets MOVE and the second gets pointer up
4562 firstWindow->consumeMotionMove();
4563 secondWindow->consumeMotionUp();
4564
4565 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004566 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4567 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004568 // The first window gets nothing and the second gets up
4569 firstWindow->consumeMotionUp();
4570 secondWindow->assertNoEvents();
4571}
4572
Arthur Hungabbb9d82021-09-01 14:52:30 +00004573// This case will create two windows and one mirrored window on the default display and mirror
4574// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4575// the windows info of second display before default display.
4576TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4577 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4578 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004579 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004580 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004581 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004582 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004583 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004584
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004585 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004586 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004587
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004588 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004589 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004590
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004591 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004592 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004593
4594 // Update window info, let it find window handle of second display first.
4595 mDispatcher->setInputWindows(
4596 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4597 {ADISPLAY_ID_DEFAULT,
4598 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4599
4600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4601 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4602 {50, 50}))
4603 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4604
4605 // Window should receive motion event.
4606 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4607
4608 // Transfer touch focus
4609 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4610 secondWindowInPrimary->getToken()));
4611 // The first window gets cancel.
4612 firstWindowInPrimary->consumeMotionCancel();
4613 secondWindowInPrimary->consumeMotionDown();
4614
4615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4616 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4617 ADISPLAY_ID_DEFAULT, {150, 50}))
4618 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4619 firstWindowInPrimary->assertNoEvents();
4620 secondWindowInPrimary->consumeMotionMove();
4621
4622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4623 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4624 {150, 50}))
4625 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4626 firstWindowInPrimary->assertNoEvents();
4627 secondWindowInPrimary->consumeMotionUp();
4628}
4629
4630// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4631// 'transferTouch' api.
4632TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4633 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4634 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004635 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004636 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004637 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004638 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004639 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004640
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004641 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004642 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004643
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004644 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004645 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004646
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004647 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004648 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004649
4650 // Update window info, let it find window handle of second display first.
4651 mDispatcher->setInputWindows(
4652 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4653 {ADISPLAY_ID_DEFAULT,
4654 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4655
4656 // Touch on second display.
4657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4658 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4659 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4660
4661 // Window should receive motion event.
4662 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4663
4664 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004665 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004666
4667 // The first window gets cancel.
4668 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4669 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4670
4671 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4672 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4673 SECOND_DISPLAY_ID, {150, 50}))
4674 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4675 firstWindowInPrimary->assertNoEvents();
4676 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4677
4678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4679 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4680 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4681 firstWindowInPrimary->assertNoEvents();
4682 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4683}
4684
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004685TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004686 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004687 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4688 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004689
Vishnu Nair47074b82020-08-14 11:54:47 -07004690 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004691 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004692 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004693
4694 window->consumeFocusEvent(true);
4695
Prabir Pradhan678438e2023-04-13 19:32:51 +00004696 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004697
4698 // Window should receive key down event.
4699 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004700
4701 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004702 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004703 mFakePolicy->assertUserActivityPoked();
4704}
4705
4706TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4707 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4708 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4709 "Fake Window", ADISPLAY_ID_DEFAULT);
4710
4711 window->setDisableUserActivity(true);
4712 window->setFocusable(true);
4713 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4714 setFocusedWindow(window);
4715
4716 window->consumeFocusEvent(true);
4717
4718 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4719
4720 // Window should receive key down event.
4721 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4722
4723 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004724 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004725 mFakePolicy->assertUserActivityNotPoked();
4726}
4727
4728TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4729 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4730 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4731 "Fake Window", ADISPLAY_ID_DEFAULT);
4732
4733 window->setFocusable(true);
4734 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4735 setFocusedWindow(window);
4736
4737 window->consumeFocusEvent(true);
4738
4739 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4740 mDispatcher->waitForIdle();
4741
4742 // System key is not passed down
4743 window->assertNoEvents();
4744
4745 // Should have poked user activity
4746 mFakePolicy->assertUserActivityPoked();
4747}
4748
4749TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4750 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4751 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4752 "Fake Window", ADISPLAY_ID_DEFAULT);
4753
4754 window->setFocusable(true);
4755 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4756 setFocusedWindow(window);
4757
4758 window->consumeFocusEvent(true);
4759
4760 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4761 mDispatcher->waitForIdle();
4762
4763 // System key is not passed down
4764 window->assertNoEvents();
4765
4766 // Should have poked user activity
4767 mFakePolicy->assertUserActivityPoked();
4768}
4769
4770TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4771 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4772 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4773 "Fake Window", ADISPLAY_ID_DEFAULT);
4774
4775 window->setDisableUserActivity(true);
4776 window->setFocusable(true);
4777 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4778 setFocusedWindow(window);
4779
4780 window->consumeFocusEvent(true);
4781
4782 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4783 mDispatcher->waitForIdle();
4784
4785 // System key is not passed down
4786 window->assertNoEvents();
4787
4788 // Should have poked user activity
4789 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004790}
4791
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004792TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
4793 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4794 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4795 "Fake Window", ADISPLAY_ID_DEFAULT);
4796
4797 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4798
4799 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4800 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4801 ADISPLAY_ID_DEFAULT, {100, 100}))
4802 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4803
4804 window->consumeMotionEvent(
4805 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
4806
4807 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004808 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004809 mFakePolicy->assertUserActivityPoked();
4810}
4811
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004812TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004813 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004814 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4815 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004816
Arthur Hung72d8dc32020-03-28 00:48:39 +00004817 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004818
Prabir Pradhan678438e2023-04-13 19:32:51 +00004819 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004820 mDispatcher->waitForIdle();
4821
4822 window->assertNoEvents();
4823}
4824
4825// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4826TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004827 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004828 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4829 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004830
Arthur Hung72d8dc32020-03-28 00:48:39 +00004831 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004832
4833 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004834 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004835 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004836 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4837 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004838
4839 // Window should receive only the motion event
4840 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4841 window->assertNoEvents(); // Key event or focus event will not be received
4842}
4843
arthurhungea3f4fc2020-12-21 23:18:53 +08004844TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4845 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4846
arthurhungea3f4fc2020-12-21 23:18:53 +08004847 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004848 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4849 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004850 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004851
arthurhungea3f4fc2020-12-21 23:18:53 +08004852 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004853 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4854 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004855 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004856
4857 // Add the windows to the dispatcher
4858 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4859
4860 PointF pointInFirst = {300, 200};
4861 PointF pointInSecond = {300, 600};
4862
4863 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004864 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4865 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4866 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004867 // Only the first window should get the down event
4868 firstWindow->consumeMotionDown();
4869 secondWindow->assertNoEvents();
4870
4871 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004872 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4873 ADISPLAY_ID_DEFAULT,
4874 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004875 // The first window gets a move and the second a down
4876 firstWindow->consumeMotionMove();
4877 secondWindow->consumeMotionDown();
4878
4879 // Send pointer cancel to the second window
4880 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004881 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004882 {pointInFirst, pointInSecond});
4883 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004884 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004885 // The first window gets move and the second gets cancel.
4886 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4887 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4888
4889 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004890 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4891 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004892 // The first window gets up and the second gets nothing.
4893 firstWindow->consumeMotionUp();
4894 secondWindow->assertNoEvents();
4895}
4896
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004897TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4898 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4899
4900 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004901 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004902 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4903 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4904 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4905 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4906
Harry Cutts33476232023-01-30 19:57:29 +00004907 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004908 window->assertNoEvents();
4909 mDispatcher->waitForIdle();
4910}
4911
chaviwd1c23182019-12-20 18:44:56 -08004912class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004913public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004914 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004915 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004916 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004917 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004918 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004919 }
4920
chaviwd1c23182019-12-20 18:44:56 -08004921 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4922
4923 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004924 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4925 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004926 }
4927
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004928 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4929
4930 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4931
chaviwd1c23182019-12-20 18:44:56 -08004932 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004933 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004934 expectedDisplayId, expectedFlags);
4935 }
4936
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004937 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004938 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004939 expectedDisplayId, expectedFlags);
4940 }
4941
chaviwd1c23182019-12-20 18:44:56 -08004942 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004943 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004944 expectedDisplayId, expectedFlags);
4945 }
4946
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004947 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004948 mInputReceiver->consumeMotionEvent(
4949 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4950 WithDisplayId(expectedDisplayId),
4951 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004952 }
4953
Arthur Hungfbfa5722021-11-16 02:45:54 +00004954 void consumeMotionPointerDown(int32_t pointerIdx) {
4955 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4956 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004957 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004958 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004959 }
4960
Evan Rosky84f07f02021-04-16 10:42:42 -07004961 MotionEvent* consumeMotion() {
4962 InputEvent* event = mInputReceiver->consume();
4963 if (!event) {
4964 ADD_FAILURE() << "No event was produced";
4965 return nullptr;
4966 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004967 if (event->getType() != InputEventType::MOTION) {
4968 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07004969 return nullptr;
4970 }
4971 return static_cast<MotionEvent*>(event);
4972 }
4973
chaviwd1c23182019-12-20 18:44:56 -08004974 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4975
4976private:
4977 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004978};
4979
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004980using InputDispatcherMonitorTest = InputDispatcherTest;
4981
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004982/**
4983 * Two entities that receive touch: A window, and a global monitor.
4984 * The touch goes to the window, and then the window disappears.
4985 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4986 * for the monitor, as well.
4987 * 1. foregroundWindow
4988 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4989 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004990TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004991 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4992 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004993 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004994
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004995 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004996
4997 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4999 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5000 {100, 200}))
5001 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5002
5003 // Both the foreground window and the global monitor should receive the touch down
5004 window->consumeMotionDown();
5005 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5006
5007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5008 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5009 ADISPLAY_ID_DEFAULT, {110, 200}))
5010 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5011
5012 window->consumeMotionMove();
5013 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5014
5015 // Now the foreground window goes away
5016 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
5017 window->consumeMotionCancel();
5018 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5019
5020 // If more events come in, there will be no more foreground window to send them to. This will
5021 // cause a cancel for the monitor, as well.
5022 ASSERT_EQ(InputEventInjectionResult::FAILED,
5023 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5024 ADISPLAY_ID_DEFAULT, {120, 200}))
5025 << "Injection should fail because the window was removed";
5026 window->assertNoEvents();
5027 // Global monitor now gets the cancel
5028 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5029}
5030
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005031TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005032 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005033 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5034 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005035 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005036
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005037 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005038
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005040 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005041 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005042 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005043 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005044}
5045
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005046TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5047 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005048
Chris Yea209fde2020-07-22 13:54:51 -07005049 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005050 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5051 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005052 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005053
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005055 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005056 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005057 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005058 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005059
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005060 // Pilfer pointers from the monitor.
5061 // This should not do anything and the window should continue to receive events.
5062 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005063
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005065 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5066 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005067 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005068
5069 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5070 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005071}
5072
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005073TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005074 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005075 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5076 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005077 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5078 window->setWindowOffset(20, 40);
5079 window->setWindowTransform(0, 1, -1, 0);
5080
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005081 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005082
5083 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5084 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5085 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5086 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5087 MotionEvent* event = monitor.consumeMotion();
5088 // Even though window has transform, gesture monitor must not.
5089 ASSERT_EQ(ui::Transform(), event->getTransform());
5090}
5091
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005092TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005093 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005094 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005095
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005096 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00005097 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005098 << "Injection should fail if there is a monitor, but no touchable window";
5099 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005100}
5101
chaviw81e2bb92019-12-18 15:03:51 -08005102TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005103 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005104 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5105 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005106
Arthur Hung72d8dc32020-03-28 00:48:39 +00005107 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08005108
5109 NotifyMotionArgs motionArgs =
5110 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5111 ADISPLAY_ID_DEFAULT);
5112
Prabir Pradhan678438e2023-04-13 19:32:51 +00005113 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005114 // Window should receive motion down event.
5115 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5116
5117 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005118 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005119 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5120 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5121 motionArgs.pointerCoords[0].getX() - 10);
5122
Prabir Pradhan678438e2023-04-13 19:32:51 +00005123 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005124 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005125 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005126}
5127
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005128/**
5129 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5130 * the device default right away. In the test scenario, we check both the default value,
5131 * and the action of enabling / disabling.
5132 */
5133TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005134 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005135 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5136 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005137 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005138
5139 // Set focused application.
5140 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005141 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005142
5143 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00005144 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005145 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005146 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005147
5148 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005149 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005150 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005151 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005152
5153 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005154 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005155 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005156 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005157 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005158 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005159 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005160 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005161
5162 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005163 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005164 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005165 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005166
5167 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005168 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005169 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005170 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005171 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005172 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005173 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005174 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005175
5176 window->assertNoEvents();
5177}
5178
Gang Wange9087892020-01-07 12:17:14 -05005179TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005180 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005181 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5182 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005183
5184 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005185 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005186
Arthur Hung72d8dc32020-03-28 00:48:39 +00005187 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005188 setFocusedWindow(window);
5189
Harry Cutts33476232023-01-30 19:57:29 +00005190 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005191
Prabir Pradhan678438e2023-04-13 19:32:51 +00005192 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5193 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005194
5195 InputEvent* event = window->consume();
5196 ASSERT_NE(event, nullptr);
5197
5198 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5199 ASSERT_NE(verified, nullptr);
5200 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5201
5202 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5203 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5204 ASSERT_EQ(keyArgs.source, verified->source);
5205 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5206
5207 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5208
5209 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005210 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005211 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005212 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5213 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5214 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5215 ASSERT_EQ(0, verifiedKey.repeatCount);
5216}
5217
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005218TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005219 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005220 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5221 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005222
5223 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5224
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005225 ui::Transform transform;
5226 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5227
5228 gui::DisplayInfo displayInfo;
5229 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5230 displayInfo.transform = transform;
5231
Patrick Williamsd828f302023-04-28 17:52:08 -05005232 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005233
Prabir Pradhan678438e2023-04-13 19:32:51 +00005234 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005235 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5236 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005237 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005238
5239 InputEvent* event = window->consume();
5240 ASSERT_NE(event, nullptr);
5241
5242 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5243 ASSERT_NE(verified, nullptr);
5244 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5245
5246 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5247 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5248 EXPECT_EQ(motionArgs.source, verified->source);
5249 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5250
5251 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5252
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005253 const vec2 rawXY =
5254 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5255 motionArgs.pointerCoords[0].getXYValue());
5256 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5257 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005258 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005259 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005260 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005261 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5262 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5263}
5264
chaviw09c8d2d2020-08-24 15:48:26 -07005265/**
5266 * Ensure that separate calls to sign the same data are generating the same key.
5267 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5268 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5269 * tests.
5270 */
5271TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5272 KeyEvent event = getTestKeyEvent();
5273 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5274
5275 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5276 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5277 ASSERT_EQ(hmac1, hmac2);
5278}
5279
5280/**
5281 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5282 */
5283TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5284 KeyEvent event = getTestKeyEvent();
5285 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5286 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5287
5288 verifiedEvent.deviceId += 1;
5289 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5290
5291 verifiedEvent.source += 1;
5292 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5293
5294 verifiedEvent.eventTimeNanos += 1;
5295 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5296
5297 verifiedEvent.displayId += 1;
5298 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5299
5300 verifiedEvent.action += 1;
5301 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5302
5303 verifiedEvent.downTimeNanos += 1;
5304 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5305
5306 verifiedEvent.flags += 1;
5307 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5308
5309 verifiedEvent.keyCode += 1;
5310 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5311
5312 verifiedEvent.scanCode += 1;
5313 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5314
5315 verifiedEvent.metaState += 1;
5316 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5317
5318 verifiedEvent.repeatCount += 1;
5319 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5320}
5321
Vishnu Nair958da932020-08-21 17:12:37 -07005322TEST_F(InputDispatcherTest, SetFocusedWindow) {
5323 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5324 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005325 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005326 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005327 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005328 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5329
5330 // Top window is also focusable but is not granted focus.
5331 windowTop->setFocusable(true);
5332 windowSecond->setFocusable(true);
5333 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5334 setFocusedWindow(windowSecond);
5335
5336 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5338 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005339
5340 // Focused window should receive event.
5341 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5342 windowTop->assertNoEvents();
5343}
5344
5345TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5346 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5347 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005348 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005349 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5350
5351 window->setFocusable(true);
5352 // Release channel for window is no longer valid.
5353 window->releaseChannel();
5354 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5355 setFocusedWindow(window);
5356
5357 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005358 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5359 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005360
5361 // window channel is invalid, so it should not receive any input event.
5362 window->assertNoEvents();
5363}
5364
5365TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5366 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5367 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005368 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005369 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005370 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5371
Vishnu Nair958da932020-08-21 17:12:37 -07005372 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5373 setFocusedWindow(window);
5374
5375 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005376 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5377 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005378
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005379 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005380 window->assertNoEvents();
5381}
5382
5383TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5384 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5385 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005386 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005387 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005388 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005389 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5390
5391 windowTop->setFocusable(true);
5392 windowSecond->setFocusable(true);
5393 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5394 setFocusedWindow(windowTop);
5395 windowTop->consumeFocusEvent(true);
5396
Chavi Weingarten847e8512023-03-29 00:26:09 +00005397 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5398 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005399 windowSecond->consumeFocusEvent(true);
5400 windowTop->consumeFocusEvent(false);
5401
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5403 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005404
5405 // Focused window should receive event.
5406 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5407}
5408
Chavi Weingarten847e8512023-03-29 00:26:09 +00005409TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005410 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5411 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005412 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005413 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005414 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005415 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5416
5417 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005418 windowSecond->setFocusable(false);
5419 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005420 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005421 setFocusedWindow(windowTop);
5422 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005423
Chavi Weingarten847e8512023-03-29 00:26:09 +00005424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5425 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005426
5427 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005428 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005429 windowSecond->assertNoEvents();
5430}
5431
5432TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5433 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5434 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005435 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005436 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005437 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5438 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005439 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5440
5441 window->setFocusable(true);
5442 previousFocusedWindow->setFocusable(true);
5443 window->setVisible(false);
5444 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5445 setFocusedWindow(previousFocusedWindow);
5446 previousFocusedWindow->consumeFocusEvent(true);
5447
5448 // Requesting focus on invisible window takes focus from currently focused window.
5449 setFocusedWindow(window);
5450 previousFocusedWindow->consumeFocusEvent(false);
5451
5452 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005453 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005454 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5455 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005456
5457 // Window does not get focus event or key down.
5458 window->assertNoEvents();
5459
5460 // Window becomes visible.
5461 window->setVisible(true);
5462 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5463
5464 // Window receives focus event.
5465 window->consumeFocusEvent(true);
5466 // Focused window receives key down.
5467 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5468}
5469
Vishnu Nair599f1412021-06-21 10:39:58 -07005470TEST_F(InputDispatcherTest, DisplayRemoved) {
5471 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5472 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005473 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005474 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5475
5476 // window is granted focus.
5477 window->setFocusable(true);
5478 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5479 setFocusedWindow(window);
5480 window->consumeFocusEvent(true);
5481
5482 // When a display is removed window loses focus.
5483 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5484 window->consumeFocusEvent(false);
5485}
5486
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005487/**
5488 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5489 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5490 * of the 'slipperyEnterWindow'.
5491 *
5492 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5493 * a way so that the touched location is no longer covered by the top window.
5494 *
5495 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5496 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5497 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5498 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5499 * with ACTION_DOWN).
5500 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5501 * window moved itself away from the touched location and had Flag::SLIPPERY.
5502 *
5503 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5504 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5505 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5506 *
5507 * In this test, we ensure that the event received by the bottom window has
5508 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5509 */
5510TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00005511 constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
5512 constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005513
5514 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5515 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5516
5517 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005518 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005519 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005520 // Make sure this one overlaps the bottom window
5521 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5522 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5523 // one. Windows with the same owner are not considered to be occluding each other.
5524 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5525
5526 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005527 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005528 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5529
5530 mDispatcher->setInputWindows(
5531 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5532
5533 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005534 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5535 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5536 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005537 slipperyExitWindow->consumeMotionDown();
5538 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5539 mDispatcher->setInputWindows(
5540 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5541
Prabir Pradhan678438e2023-04-13 19:32:51 +00005542 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5543 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5544 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005545
5546 slipperyExitWindow->consumeMotionCancel();
5547
5548 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5549 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5550}
5551
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005552/**
5553 * Two windows, one on the left and another on the right. The left window is slippery. The right
5554 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5555 * touch moves from the left window into the right window, the gesture should continue to go to the
5556 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5557 * reproduces a crash.
5558 */
5559TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5560 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5561
5562 sp<FakeWindowHandle> leftSlipperyWindow =
5563 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5564 leftSlipperyWindow->setSlippery(true);
5565 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5566
5567 sp<FakeWindowHandle> rightDropTouchesWindow =
5568 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5569 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5570 rightDropTouchesWindow->setDropInput(true);
5571
5572 mDispatcher->setInputWindows(
5573 {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}});
5574
5575 // Start touch in the left window
5576 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5577 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5578 .build());
5579 leftSlipperyWindow->consumeMotionDown();
5580
5581 // And move it into the right window
5582 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5583 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5584 .build());
5585
5586 // Since the right window isn't eligible to receive input, touch does not slip.
5587 // The left window continues to receive the gesture.
5588 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5589 rightDropTouchesWindow->assertNoEvents();
5590}
5591
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005592TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
5593 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5594
5595 sp<FakeWindowHandle> leftWindow =
5596 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5597 leftWindow->setFrame(Rect(0, 0, 100, 100));
5598 leftWindow->setOwnerInfo(1, 101);
5599
5600 sp<FakeWindowHandle> rightSpy =
5601 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
5602 rightSpy->setFrame(Rect(100, 0, 200, 100));
5603 rightSpy->setOwnerInfo(2, 102);
5604 rightSpy->setSpy(true);
5605 rightSpy->setTrustedOverlay(true);
5606
5607 sp<FakeWindowHandle> rightWindow =
5608 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5609 rightWindow->setFrame(Rect(100, 0, 200, 100));
5610 rightWindow->setOwnerInfo(3, 103);
5611
5612 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightSpy, rightWindow, leftWindow}}});
5613
5614 // Touch in the left window
5615 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5616 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5617 .build());
5618 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
5619 mDispatcher->waitForIdle();
5620 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {101}));
5621
5622 // Touch another finger over the right windows
5623 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5624 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5625 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5626 .build());
5627 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
5628 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
5629 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
5630 mDispatcher->waitForIdle();
5631 ASSERT_NO_FATAL_FAILURE(
5632 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {101, 102, 103}));
5633
5634 // Release finger over left window. The UP actions are not treated as device interaction.
5635 // The windows that did not receive the UP pointer will receive MOVE events, but since this
5636 // is part of the UP action, we do not treat this as device interaction.
5637 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
5638 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5639 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5640 .build());
5641 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
5642 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5643 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5644 mDispatcher->waitForIdle();
5645 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5646
5647 // Move remaining finger
5648 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5649 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5650 .build());
5651 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5652 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5653 mDispatcher->waitForIdle();
5654 ASSERT_NO_FATAL_FAILURE(
5655 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {102, 103}));
5656
5657 // Release all fingers
5658 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5659 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5660 .build());
5661 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
5662 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
5663 mDispatcher->waitForIdle();
5664 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5665}
5666
5667TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
5668 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5669
5670 sp<FakeWindowHandle> window =
5671 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5672 window->setFrame(Rect(0, 0, 100, 100));
5673 window->setOwnerInfo(1, 101);
5674
5675 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5676 setFocusedWindow(window);
5677 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
5678
5679 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
5680 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
5681 mDispatcher->waitForIdle();
5682 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {101}));
5683
5684 // The UP actions are not treated as device interaction.
5685 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
5686 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
5687 mDispatcher->waitForIdle();
5688 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5689}
5690
Garfield Tan1c7bc862020-01-28 13:24:04 -08005691class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5692protected:
5693 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5694 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5695
Chris Yea209fde2020-07-22 13:54:51 -07005696 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005697 sp<FakeWindowHandle> mWindow;
5698
5699 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005700 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005701 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Prabir Pradhana41d2442023-04-20 21:30:40 +00005702 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Prabir Pradhan87112a72023-04-20 19:13:39 +00005703 mDispatcher->requestRefreshConfiguration();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005704 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
5705 ASSERT_EQ(OK, mDispatcher->start());
5706
5707 setUpWindow();
5708 }
5709
5710 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005711 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005712 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005713
Vishnu Nair47074b82020-08-14 11:54:47 -07005714 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005715 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005716 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005717 mWindow->consumeFocusEvent(true);
5718 }
5719
Chris Ye2ad95392020-09-01 13:44:44 -07005720 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005721 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005722 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005723 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005724 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005725
5726 // Window should receive key down event.
5727 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5728 }
5729
5730 void expectKeyRepeatOnce(int32_t repeatCount) {
5731 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5732 InputEvent* repeatEvent = mWindow->consume();
5733 ASSERT_NE(nullptr, repeatEvent);
5734
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005735 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005736
5737 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5738 uint32_t eventAction = repeatKeyEvent->getAction();
5739 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5740 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5741 }
5742
Chris Ye2ad95392020-09-01 13:44:44 -07005743 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005744 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005745 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005746 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005747 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005748
5749 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005750 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005751 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005752 }
5753};
5754
5755TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005756 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005757 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5758 expectKeyRepeatOnce(repeatCount);
5759 }
5760}
5761
5762TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005763 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005764 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5765 expectKeyRepeatOnce(repeatCount);
5766 }
Harry Cutts33476232023-01-30 19:57:29 +00005767 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005768 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005769 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5770 expectKeyRepeatOnce(repeatCount);
5771 }
5772}
5773
5774TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005775 sendAndConsumeKeyDown(/*deviceId=*/1);
5776 expectKeyRepeatOnce(/*repeatCount=*/1);
5777 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005778 mWindow->assertNoEvents();
5779}
5780
5781TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005782 sendAndConsumeKeyDown(/*deviceId=*/1);
5783 expectKeyRepeatOnce(/*repeatCount=*/1);
5784 sendAndConsumeKeyDown(/*deviceId=*/2);
5785 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005786 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005787 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005788 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005789 expectKeyRepeatOnce(/*repeatCount=*/2);
5790 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005791 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005792 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005793 mWindow->assertNoEvents();
5794}
5795
5796TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005797 sendAndConsumeKeyDown(/*deviceId=*/1);
5798 expectKeyRepeatOnce(/*repeatCount=*/1);
5799 sendAndConsumeKeyDown(/*deviceId=*/2);
5800 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005801 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005802 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005803 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005804 mWindow->assertNoEvents();
5805}
5806
liushenxiang42232912021-05-21 20:24:09 +08005807TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5808 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005809 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005810 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005811 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5812 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5813 mWindow->assertNoEvents();
5814}
5815
Garfield Tan1c7bc862020-01-28 13:24:04 -08005816TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005817 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005818 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005819 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5820 InputEvent* repeatEvent = mWindow->consume();
5821 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5822 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5823 IdGenerator::getSource(repeatEvent->getId()));
5824 }
5825}
5826
5827TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005828 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005829 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005830
5831 std::unordered_set<int32_t> idSet;
5832 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5833 InputEvent* repeatEvent = mWindow->consume();
5834 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5835 int32_t id = repeatEvent->getId();
5836 EXPECT_EQ(idSet.end(), idSet.find(id));
5837 idSet.insert(id);
5838 }
5839}
5840
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005841/* Test InputDispatcher for MultiDisplay */
5842class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5843public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005844 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005845 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005846
Chris Yea209fde2020-07-22 13:54:51 -07005847 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005848 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005849 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005850
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005851 // Set focus window for primary display, but focused display would be second one.
5852 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005853 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005854 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005855 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005856 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005857
Chris Yea209fde2020-07-22 13:54:51 -07005858 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005859 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005860 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005861 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005862 // Set focus display to second one.
5863 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5864 // Set focus window for second display.
5865 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005866 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005867 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005868 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005869 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005870 }
5871
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005872 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005873 InputDispatcherTest::TearDown();
5874
Chris Yea209fde2020-07-22 13:54:51 -07005875 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005876 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005877 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005878 windowInSecondary.clear();
5879 }
5880
5881protected:
Chris Yea209fde2020-07-22 13:54:51 -07005882 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005883 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005884 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005885 sp<FakeWindowHandle> windowInSecondary;
5886};
5887
5888TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5889 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5891 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5892 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005893 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005894 windowInSecondary->assertNoEvents();
5895
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005896 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5898 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5899 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005900 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005901 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005902}
5903
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005904TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005905 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5907 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005908 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005909 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005910 windowInSecondary->assertNoEvents();
5911
5912 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005914 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005915 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005916 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005917
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005918 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005919 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005920
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005921 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005922 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005923 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005924
5925 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005926 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005927 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005928 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005929 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005930 windowInSecondary->assertNoEvents();
5931}
5932
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005933// Test per-display input monitors for motion event.
5934TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005935 FakeMonitorReceiver monitorInPrimary =
5936 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5937 FakeMonitorReceiver monitorInSecondary =
5938 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005939
5940 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5942 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5943 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005944 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005945 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005946 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005947 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005948
5949 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5951 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5952 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005953 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005954 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005955 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005956 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005957
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005958 // Lift up the touch from the second display
5959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5960 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5961 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5962 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5963 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5964
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005965 // Test inject a non-pointer motion event.
5966 // If specific a display, it will dispatch to the focused window of particular display,
5967 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005968 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5969 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5970 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005971 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005972 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005973 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005974 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005975}
5976
5977// Test per-display input monitors for key event.
5978TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005979 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005980 FakeMonitorReceiver monitorInPrimary =
5981 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5982 FakeMonitorReceiver monitorInSecondary =
5983 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005984
5985 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5987 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005988 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005989 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005990 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005991 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005992}
5993
Vishnu Nair958da932020-08-21 17:12:37 -07005994TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
5995 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005996 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005997 secondWindowInPrimary->setFocusable(true);
5998 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
5999 setFocusedWindow(secondWindowInPrimary);
6000 windowInPrimary->consumeFocusEvent(false);
6001 secondWindowInPrimary->consumeFocusEvent(true);
6002
6003 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006004 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
6005 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006006 windowInPrimary->assertNoEvents();
6007 windowInSecondary->assertNoEvents();
6008 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6009}
6010
Arthur Hungdfd528e2021-12-08 13:23:04 +00006011TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6012 FakeMonitorReceiver monitorInPrimary =
6013 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6014 FakeMonitorReceiver monitorInSecondary =
6015 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6016
6017 // Test touch down on primary display.
6018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6019 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6020 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6021 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6022 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6023
6024 // Test touch down on second display.
6025 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6026 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
6027 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6028 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6029 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6030
6031 // Trigger cancel touch.
6032 mDispatcher->cancelCurrentTouch();
6033 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6034 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6035 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6036 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6037
6038 // Test inject a move motion event, no window/monitor should receive the event.
6039 ASSERT_EQ(InputEventInjectionResult::FAILED,
6040 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6041 ADISPLAY_ID_DEFAULT, {110, 200}))
6042 << "Inject motion event should return InputEventInjectionResult::FAILED";
6043 windowInPrimary->assertNoEvents();
6044 monitorInPrimary.assertNoEvents();
6045
6046 ASSERT_EQ(InputEventInjectionResult::FAILED,
6047 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6048 SECOND_DISPLAY_ID, {110, 200}))
6049 << "Inject motion event should return InputEventInjectionResult::FAILED";
6050 windowInSecondary->assertNoEvents();
6051 monitorInSecondary.assertNoEvents();
6052}
6053
Jackal Guof9696682018-10-05 12:23:23 +08006054class InputFilterTest : public InputDispatcherTest {
6055protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006056 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6057 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006058 NotifyMotionArgs motionArgs;
6059
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006060 motionArgs =
6061 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006062 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006063 motionArgs =
6064 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006065 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006066 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006067 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006068 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
6069 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006070 } else {
6071 mFakePolicy->assertFilterInputEventWasNotCalled();
6072 }
6073 }
6074
6075 void testNotifyKey(bool expectToBeFiltered) {
6076 NotifyKeyArgs keyArgs;
6077
6078 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006079 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006080 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006081 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006082 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006083
6084 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006085 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006086 } else {
6087 mFakePolicy->assertFilterInputEventWasNotCalled();
6088 }
6089 }
6090};
6091
6092// Test InputFilter for MotionEvent
6093TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6094 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
6095 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
6096 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
6097
6098 // Enable InputFilter
6099 mDispatcher->setInputFilterEnabled(true);
6100 // Test touch on both primary and second display, and check if both events are filtered.
6101 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
6102 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
6103
6104 // Disable InputFilter
6105 mDispatcher->setInputFilterEnabled(false);
6106 // Test touch on both primary and second display, and check if both events aren't filtered.
6107 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
6108 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
6109}
6110
6111// Test InputFilter for KeyEvent
6112TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6113 // Since the InputFilter is disabled by default, check if key event aren't filtered.
6114 testNotifyKey(/*expectToBeFiltered*/ false);
6115
6116 // Enable InputFilter
6117 mDispatcher->setInputFilterEnabled(true);
6118 // Send a key event, and check if it is filtered.
6119 testNotifyKey(/*expectToBeFiltered*/ true);
6120
6121 // Disable InputFilter
6122 mDispatcher->setInputFilterEnabled(false);
6123 // Send a key event, and check if it isn't filtered.
6124 testNotifyKey(/*expectToBeFiltered*/ false);
6125}
6126
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006127// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6128// logical display coordinate space.
6129TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6130 ui::Transform firstDisplayTransform;
6131 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6132 ui::Transform secondDisplayTransform;
6133 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6134
6135 std::vector<gui::DisplayInfo> displayInfos(2);
6136 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6137 displayInfos[0].transform = firstDisplayTransform;
6138 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6139 displayInfos[1].transform = secondDisplayTransform;
6140
Patrick Williamsd828f302023-04-28 17:52:08 -05006141 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006142
6143 // Enable InputFilter
6144 mDispatcher->setInputFilterEnabled(true);
6145
6146 // Ensure the correct transforms are used for the displays.
6147 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
6148 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
6149}
6150
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006151class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6152protected:
6153 virtual void SetUp() override {
6154 InputDispatcherTest::SetUp();
6155
6156 /**
6157 * We don't need to enable input filter to test the injected event policy, but we enabled it
6158 * here to make the tests more realistic, since this policy only matters when inputfilter is
6159 * on.
6160 */
6161 mDispatcher->setInputFilterEnabled(true);
6162
6163 std::shared_ptr<InputApplicationHandle> application =
6164 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006165 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6166 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006167
6168 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6169 mWindow->setFocusable(true);
6170 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6171 setFocusedWindow(mWindow);
6172 mWindow->consumeFocusEvent(true);
6173 }
6174
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006175 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6176 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006177 KeyEvent event;
6178
6179 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6180 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6181 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006182 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006183 const int32_t additionalPolicyFlags =
6184 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006186 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006187 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6188 policyFlags | additionalPolicyFlags));
6189
6190 InputEvent* received = mWindow->consume();
6191 ASSERT_NE(nullptr, received);
6192 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006193 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006194 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
6195 ASSERT_EQ(flags, keyEvent.getFlags());
6196 }
6197
6198 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6199 int32_t flags) {
6200 MotionEvent event;
6201 PointerProperties pointerProperties[1];
6202 PointerCoords pointerCoords[1];
6203 pointerProperties[0].clear();
6204 pointerProperties[0].id = 0;
6205 pointerCoords[0].clear();
6206 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6207 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6208
6209 ui::Transform identityTransform;
6210 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6211 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6212 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6213 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6214 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006215 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006216 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006217 /*pointerCount*/ 1, pointerProperties, pointerCoords);
6218
6219 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6220 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006221 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006222 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6223 policyFlags | additionalPolicyFlags));
6224
6225 InputEvent* received = mWindow->consume();
6226 ASSERT_NE(nullptr, received);
6227 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006228 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006229 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
6230 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006231 }
6232
6233private:
6234 sp<FakeWindowHandle> mWindow;
6235};
6236
6237TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006238 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6239 // filter. Without it, the event will no different from a regularly injected event, and the
6240 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006241 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6242 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006243}
6244
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006245TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006246 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006247 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006248 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6249}
6250
6251TEST_F(InputFilterInjectionPolicyTest,
6252 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6253 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006254 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006255 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006256}
6257
6258TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006259 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6260 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006261}
6262
chaviwfd6d3512019-03-25 13:23:49 -07006263class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006264 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006265 InputDispatcherTest::SetUp();
6266
Chris Yea209fde2020-07-22 13:54:51 -07006267 std::shared_ptr<FakeApplicationHandle> application =
6268 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006269 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006270 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006271 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006272
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006273 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006274 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006275 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006276
6277 // Set focused application.
6278 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006279 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006280
6281 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00006282 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006283 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006284 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006285 }
6286
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006287 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006288 InputDispatcherTest::TearDown();
6289
6290 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006291 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006292 }
6293
6294protected:
6295 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006296 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006297 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006298};
6299
6300// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6301// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6302// the onPointerDownOutsideFocus callback.
6303TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006304 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006305 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6306 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006307 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006308 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006309
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006310 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006311 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6312}
6313
6314// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6315// DOWN on the window that doesn't have focus. Ensure no window received the
6316// onPointerDownOutsideFocus callback.
6317TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006319 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006320 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006321 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006322
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006323 ASSERT_TRUE(mDispatcher->waitForIdle());
6324 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006325}
6326
6327// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6328// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6329TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6331 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006332 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006333 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006334
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006335 ASSERT_TRUE(mDispatcher->waitForIdle());
6336 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006337}
6338
6339// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6340// DOWN on the window that already has focus. Ensure no window received the
6341// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006342TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006343 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006344 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006345 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006346 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006347 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006348
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006349 ASSERT_TRUE(mDispatcher->waitForIdle());
6350 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006351}
6352
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006353// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6354// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6355TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6356 const MotionEvent event =
6357 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6358 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006359 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006360 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6361 .build();
6362 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6363 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6364 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6365
6366 ASSERT_TRUE(mDispatcher->waitForIdle());
6367 mFakePolicy->assertOnPointerDownWasNotCalled();
6368 // Ensure that the unfocused window did not receive any FOCUS events.
6369 mUnfocusedWindow->assertNoEvents();
6370}
6371
chaviwaf87b3e2019-10-01 16:59:28 -07006372// These tests ensures we can send touch events to a single client when there are multiple input
6373// windows that point to the same client token.
6374class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6375 virtual void SetUp() override {
6376 InputDispatcherTest::SetUp();
6377
Chris Yea209fde2020-07-22 13:54:51 -07006378 std::shared_ptr<FakeApplicationHandle> application =
6379 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006380 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6381 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006382 mWindow1->setFrame(Rect(0, 0, 100, 100));
6383
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006384 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6385 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006386 mWindow2->setFrame(Rect(100, 100, 200, 200));
6387
Arthur Hung72d8dc32020-03-28 00:48:39 +00006388 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006389 }
6390
6391protected:
6392 sp<FakeWindowHandle> mWindow1;
6393 sp<FakeWindowHandle> mWindow2;
6394
6395 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006396 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006397 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6398 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006399 }
6400
6401 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6402 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006403 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006404 InputEvent* event = window->consume();
6405
6406 ASSERT_NE(nullptr, event) << name.c_str()
6407 << ": consumer should have returned non-NULL event.";
6408
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006409 ASSERT_EQ(InputEventType::MOTION, event->getType())
6410 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006411
6412 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006413 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006414 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006415
6416 for (size_t i = 0; i < points.size(); i++) {
6417 float expectedX = points[i].x;
6418 float expectedY = points[i].y;
6419
6420 EXPECT_EQ(expectedX, motionEvent.getX(i))
6421 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6422 << ", got " << motionEvent.getX(i);
6423 EXPECT_EQ(expectedY, motionEvent.getY(i))
6424 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6425 << ", got " << motionEvent.getY(i);
6426 }
6427 }
chaviw9eaa22c2020-07-01 16:21:27 -07006428
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006429 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006430 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006431 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6432 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006433
6434 // Always consume from window1 since it's the window that has the InputReceiver
6435 consumeMotionEvent(mWindow1, action, expectedPoints);
6436 }
chaviwaf87b3e2019-10-01 16:59:28 -07006437};
6438
6439TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6440 // Touch Window 1
6441 PointF touchedPoint = {10, 10};
6442 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006443 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006444
6445 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006446 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006447
6448 // Touch Window 2
6449 touchedPoint = {150, 150};
6450 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006451 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006452}
6453
chaviw9eaa22c2020-07-01 16:21:27 -07006454TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6455 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006456 mWindow2->setWindowScale(0.5f, 0.5f);
6457
6458 // Touch Window 1
6459 PointF touchedPoint = {10, 10};
6460 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006461 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006462 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006463 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006464
6465 // Touch Window 2
6466 touchedPoint = {150, 150};
6467 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006468 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6469 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006470
chaviw9eaa22c2020-07-01 16:21:27 -07006471 // Update the transform so rotation is set
6472 mWindow2->setWindowTransform(0, -1, 1, 0);
6473 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6474 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006475}
6476
chaviw9eaa22c2020-07-01 16:21:27 -07006477TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006478 mWindow2->setWindowScale(0.5f, 0.5f);
6479
6480 // Touch Window 1
6481 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6482 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006483 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006484
6485 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006486 touchedPoints.push_back(PointF{150, 150});
6487 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006488 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006489
chaviw9eaa22c2020-07-01 16:21:27 -07006490 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006491 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006492 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006493
chaviw9eaa22c2020-07-01 16:21:27 -07006494 // Update the transform so rotation is set for Window 2
6495 mWindow2->setWindowTransform(0, -1, 1, 0);
6496 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006497 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006498}
6499
chaviw9eaa22c2020-07-01 16:21:27 -07006500TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006501 mWindow2->setWindowScale(0.5f, 0.5f);
6502
6503 // Touch Window 1
6504 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6505 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006506 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006507
6508 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006509 touchedPoints.push_back(PointF{150, 150});
6510 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006511
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006512 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006513
6514 // Move both windows
6515 touchedPoints = {{20, 20}, {175, 175}};
6516 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6517 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6518
chaviw9eaa22c2020-07-01 16:21:27 -07006519 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006520
chaviw9eaa22c2020-07-01 16:21:27 -07006521 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006522 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006523 expectedPoints.pop_back();
6524
6525 // Touch Window 2
6526 mWindow2->setWindowTransform(0, -1, 1, 0);
6527 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006528 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006529
6530 // Move both windows
6531 touchedPoints = {{20, 20}, {175, 175}};
6532 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6533 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6534
6535 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006536}
6537
6538TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6539 mWindow1->setWindowScale(0.5f, 0.5f);
6540
6541 // Touch Window 1
6542 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6543 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006544 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006545
6546 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006547 touchedPoints.push_back(PointF{150, 150});
6548 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006549
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006550 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006551
6552 // Move both windows
6553 touchedPoints = {{20, 20}, {175, 175}};
6554 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6555 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6556
chaviw9eaa22c2020-07-01 16:21:27 -07006557 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006558}
6559
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006560/**
6561 * When one of the windows is slippery, the touch should not slip into the other window with the
6562 * same input channel.
6563 */
6564TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6565 mWindow1->setSlippery(true);
6566 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6567
6568 // Touch down in window 1
6569 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6570 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6571 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6572
6573 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6574 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6575 // getting generated.
6576 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6577 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6578
6579 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6580}
6581
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006582/**
6583 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
6584 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
6585 * that the pointer is hovering over may have a different transform.
6586 */
6587TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
6588 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6589
6590 // Start hover in window 1
6591 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
6592 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6593 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6594 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
6595
6596 // Move hover to window 2.
6597 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6598 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6599
6600 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
6601 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6602 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
6603}
6604
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006605class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6606 virtual void SetUp() override {
6607 InputDispatcherTest::SetUp();
6608
Chris Yea209fde2020-07-22 13:54:51 -07006609 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006610 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006611 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6612 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006613 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006614 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006615 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006616
6617 // Set focused application.
6618 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6619
6620 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006621 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006622 mWindow->consumeFocusEvent(true);
6623 }
6624
6625 virtual void TearDown() override {
6626 InputDispatcherTest::TearDown();
6627 mWindow.clear();
6628 }
6629
6630protected:
Chris Yea209fde2020-07-22 13:54:51 -07006631 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006632 sp<FakeWindowHandle> mWindow;
6633 static constexpr PointF WINDOW_LOCATION = {20, 20};
6634
6635 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006636 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006637 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6638 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006640 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6641 WINDOW_LOCATION));
6642 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006643
6644 sp<FakeWindowHandle> addSpyWindow() {
6645 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006646 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006647 spy->setTrustedOverlay(true);
6648 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006649 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006650 spy->setDispatchingTimeout(30ms);
6651 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6652 return spy;
6653 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006654};
6655
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006656// Send a tap and respond, which should not cause an ANR.
6657TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6658 tapOnWindow();
6659 mWindow->consumeMotionDown();
6660 mWindow->consumeMotionUp();
6661 ASSERT_TRUE(mDispatcher->waitForIdle());
6662 mFakePolicy->assertNotifyAnrWasNotCalled();
6663}
6664
6665// Send a regular key and respond, which should not cause an ANR.
6666TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006668 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6669 ASSERT_TRUE(mDispatcher->waitForIdle());
6670 mFakePolicy->assertNotifyAnrWasNotCalled();
6671}
6672
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006673TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6674 mWindow->setFocusable(false);
6675 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6676 mWindow->consumeFocusEvent(false);
6677
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006678 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006679 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6680 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6681 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006682 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006683 // Key will not go to window because we have no focused window.
6684 // The 'no focused window' ANR timer should start instead.
6685
6686 // Now, the focused application goes away.
6687 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6688 // The key should get dropped and there should be no ANR.
6689
6690 ASSERT_TRUE(mDispatcher->waitForIdle());
6691 mFakePolicy->assertNotifyAnrWasNotCalled();
6692}
6693
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006694// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006695// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6696// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006697TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006698 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006699 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6700 WINDOW_LOCATION));
6701
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006702 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6703 ASSERT_TRUE(sequenceNum);
6704 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006705 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006706
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006707 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006708 mWindow->consumeMotionEvent(
6709 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006710 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006711 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006712}
6713
6714// Send a key to the app and have the app not respond right away.
6715TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6716 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006718 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6719 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006720 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006721 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006722 ASSERT_TRUE(mDispatcher->waitForIdle());
6723}
6724
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006725// We have a focused application, but no focused window
6726TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006727 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006728 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6729 mWindow->consumeFocusEvent(false);
6730
6731 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006732 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006733 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6734 WINDOW_LOCATION));
6735 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6736 mDispatcher->waitForIdle();
6737 mFakePolicy->assertNotifyAnrWasNotCalled();
6738
6739 // Once a focused event arrives, we get an ANR for this application
6740 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6741 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006742 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006743 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6744 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006745 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006746 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006747 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006748 ASSERT_TRUE(mDispatcher->waitForIdle());
6749}
6750
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006751/**
6752 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6753 * there will not be an ANR.
6754 */
6755TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6756 mWindow->setFocusable(false);
6757 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6758 mWindow->consumeFocusEvent(false);
6759
6760 KeyEvent event;
6761 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6762 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6763
6764 // Define a valid key down event that is stale (too old).
6765 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6766 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006767 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006768
6769 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6770
6771 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006772 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006773 InputEventInjectionSync::WAIT_FOR_RESULT,
6774 INJECT_EVENT_TIMEOUT, policyFlags);
6775 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6776 << "Injection should fail because the event is stale";
6777
6778 ASSERT_TRUE(mDispatcher->waitForIdle());
6779 mFakePolicy->assertNotifyAnrWasNotCalled();
6780 mWindow->assertNoEvents();
6781}
6782
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006783// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006784// Make sure that we don't notify policy twice about the same ANR.
6785TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006786 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006787 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6788 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006789
6790 // Once a focused event arrives, we get an ANR for this application
6791 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6792 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006793 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006794 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6795 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006796 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006797 const std::chrono::duration appTimeout =
6798 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6799 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006800
Vishnu Naire4df8752022-09-08 09:17:55 -07006801 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006802 // ANR should not be raised again. It is up to policy to do that if it desires.
6803 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006804
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006805 // If we now get a focused window, the ANR should stop, but the policy handles that via
6806 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006807 ASSERT_TRUE(mDispatcher->waitForIdle());
6808}
6809
6810// We have a focused application, but no focused window
6811TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006812 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006813 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6814 mWindow->consumeFocusEvent(false);
6815
6816 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006817 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006818 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006819 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6820 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006821
Vishnu Naire4df8752022-09-08 09:17:55 -07006822 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6823 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006824
6825 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006826 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006827 ASSERT_TRUE(mDispatcher->waitForIdle());
6828 mWindow->assertNoEvents();
6829}
6830
6831/**
6832 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6833 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6834 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6835 * the ANR mechanism should still work.
6836 *
6837 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6838 * DOWN event, while not responding on the second one.
6839 */
6840TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6841 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6842 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6843 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6844 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6845 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006846 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006847
6848 // Now send ACTION_UP, with identical timestamp
6849 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6850 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6851 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6852 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006853 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006854
6855 // We have now sent down and up. Let's consume first event and then ANR on the second.
6856 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6857 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006858 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006859}
6860
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006861// A spy window can receive an ANR
6862TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6863 sp<FakeWindowHandle> spy = addSpyWindow();
6864
6865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6866 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6867 WINDOW_LOCATION));
6868 mWindow->consumeMotionDown();
6869
6870 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6871 ASSERT_TRUE(sequenceNum);
6872 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006873 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006874
6875 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006876 spy->consumeMotionEvent(
6877 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006878 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006879 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006880}
6881
6882// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006883// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006884TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6885 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006886
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006887 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6888 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006889 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006891
6892 // Stuck on the ACTION_UP
6893 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006894 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006895
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006896 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006897 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006898 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6899 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006900
6901 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6902 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006903 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006904 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006905 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006906}
6907
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006908// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006909// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006910TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6911 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006912
6913 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006914 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6915 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006916
6917 mWindow->consumeMotionDown();
6918 // Stuck on the ACTION_UP
6919 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006920 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006921
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006922 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006923 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006924 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6925 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006926
6927 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6928 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006929 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006930 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006931 spy->assertNoEvents();
6932}
6933
6934TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6935 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6936
6937 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6938
6939 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6940 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6941 WINDOW_LOCATION));
6942
6943 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6944 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6945 ASSERT_TRUE(consumeSeq);
6946
Prabir Pradhanedd96402022-02-15 01:46:16 -08006947 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006948
6949 monitor.finishEvent(*consumeSeq);
6950 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6951
6952 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006953 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006954}
6955
6956// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6957// process events, you don't get an anr. When the window later becomes unresponsive again, you
6958// get an ANR again.
6959// 1. tap -> block on ACTION_UP -> receive ANR
6960// 2. consume all pending events (= queue becomes healthy again)
6961// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6962TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6963 tapOnWindow();
6964
6965 mWindow->consumeMotionDown();
6966 // Block on ACTION_UP
6967 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006968 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006969 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6970 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006971 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006972 mWindow->assertNoEvents();
6973
6974 tapOnWindow();
6975 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006976 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006977 mWindow->consumeMotionUp();
6978
6979 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006980 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006981 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006982 mWindow->assertNoEvents();
6983}
6984
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006985// If a connection remains unresponsive for a while, make sure policy is only notified once about
6986// it.
6987TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006989 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6990 WINDOW_LOCATION));
6991
6992 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006993 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006994 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006995 // 'notifyConnectionUnresponsive' should only be called once per connection
6996 mFakePolicy->assertNotifyAnrWasNotCalled();
6997 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006998 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006999 mWindow->consumeMotionEvent(
7000 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007001 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007002 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007003 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007004 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007005}
7006
7007/**
7008 * If a window is processing a motion event, and then a key event comes in, the key event should
7009 * not to to the focused window until the motion is processed.
7010 *
7011 * Warning!!!
7012 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7013 * and the injection timeout that we specify when injecting the key.
7014 * We must have the injection timeout (10ms) be smaller than
7015 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7016 *
7017 * If that value changes, this test should also change.
7018 */
7019TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7020 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7021 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7022
7023 tapOnWindow();
7024 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7025 ASSERT_TRUE(downSequenceNum);
7026 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7027 ASSERT_TRUE(upSequenceNum);
7028 // Don't finish the events yet, and send a key
7029 // Injection will "succeed" because we will eventually give up and send the key to the focused
7030 // window even if motions are still being processed. But because the injection timeout is short,
7031 // we will receive INJECTION_TIMED_OUT as the result.
7032
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007033 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007034 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007035 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
7036 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007037 // Key will not be sent to the window, yet, because the window is still processing events
7038 // and the key remains pending, waiting for the touch events to be processed
7039 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7040 ASSERT_FALSE(keySequenceNum);
7041
7042 std::this_thread::sleep_for(500ms);
7043 // if we wait long enough though, dispatcher will give up, and still send the key
7044 // to the focused window, even though we have not yet finished the motion event
7045 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7046 mWindow->finishEvent(*downSequenceNum);
7047 mWindow->finishEvent(*upSequenceNum);
7048}
7049
7050/**
7051 * If a window is processing a motion event, and then a key event comes in, the key event should
7052 * not go to the focused window until the motion is processed.
7053 * If then a new motion comes in, then the pending key event should be going to the currently
7054 * focused window right away.
7055 */
7056TEST_F(InputDispatcherSingleWindowAnr,
7057 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7058 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7059 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7060
7061 tapOnWindow();
7062 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7063 ASSERT_TRUE(downSequenceNum);
7064 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7065 ASSERT_TRUE(upSequenceNum);
7066 // Don't finish the events yet, and send a key
7067 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007068 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007069 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7070 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007071 // At this point, key is still pending, and should not be sent to the application yet.
7072 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7073 ASSERT_FALSE(keySequenceNum);
7074
7075 // Now tap down again. It should cause the pending key to go to the focused window right away.
7076 tapOnWindow();
7077 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7078 // the other events yet. We can finish events in any order.
7079 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7080 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7081 mWindow->consumeMotionDown();
7082 mWindow->consumeMotionUp();
7083 mWindow->assertNoEvents();
7084}
7085
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007086/**
7087 * Send an event to the app and have the app not respond right away.
7088 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7089 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7090 * At some point, the window becomes responsive again.
7091 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7092 */
7093TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7094 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7095 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7096 .build());
7097
7098 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7099 ASSERT_TRUE(sequenceNum);
7100 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7101 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7102
7103 mWindow->finishEvent(*sequenceNum);
7104 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7105 ASSERT_TRUE(mDispatcher->waitForIdle());
7106 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7107
7108 // Now that the window is responsive, let's continue the gesture.
7109 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7110 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7111 .build());
7112
7113 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7114 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7115 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7116 .build());
7117
7118 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7119 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7120 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7121 .build());
7122 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7123 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7124 .build());
7125 // We already canceled this pointer, so the window shouldn't get any new events.
7126 mWindow->assertNoEvents();
7127
7128 // Start another one.
7129 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7130 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7131 .build());
7132 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7133}
7134
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007135class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7136 virtual void SetUp() override {
7137 InputDispatcherTest::SetUp();
7138
Chris Yea209fde2020-07-22 13:54:51 -07007139 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007140 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007141 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7142 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007143 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007144 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007145 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007146
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007147 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7148 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05007149 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007150 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007151
7152 // Set focused application.
7153 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007154 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007155
7156 // Expect one focus window exist in display.
7157 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007158 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007159 mFocusedWindow->consumeFocusEvent(true);
7160 }
7161
7162 virtual void TearDown() override {
7163 InputDispatcherTest::TearDown();
7164
7165 mUnfocusedWindow.clear();
7166 mFocusedWindow.clear();
7167 }
7168
7169protected:
Chris Yea209fde2020-07-22 13:54:51 -07007170 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007171 sp<FakeWindowHandle> mUnfocusedWindow;
7172 sp<FakeWindowHandle> mFocusedWindow;
7173 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7174 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7175 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7176
7177 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7178
7179 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7180
7181private:
7182 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007184 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7185 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007186 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007187 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7188 location));
7189 }
7190};
7191
7192// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7193// should be ANR'd first.
7194TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007196 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7197 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007198 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007199 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007200 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007201 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007202 // We consumed all events, so no ANR
7203 ASSERT_TRUE(mDispatcher->waitForIdle());
7204 mFakePolicy->assertNotifyAnrWasNotCalled();
7205
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007206 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007207 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7208 FOCUSED_WINDOW_LOCATION));
7209 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7210 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007211
7212 const std::chrono::duration timeout =
7213 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007214 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007215 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7216 // sequence to make it consistent
7217 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007218 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007219 mFocusedWindow->consumeMotionDown();
7220 // This cancel is generated because the connection was unresponsive
7221 mFocusedWindow->consumeMotionCancel();
7222 mFocusedWindow->assertNoEvents();
7223 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007224 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007225 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7226 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007227 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007228}
7229
7230// If we have 2 windows with identical timeouts that are both unresponsive,
7231// it doesn't matter which order they should have ANR.
7232// But we should receive ANR for both.
7233TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7234 // Set the timeout for unfocused window to match the focused window
7235 mUnfocusedWindow->setDispatchingTimeout(10ms);
7236 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7237
7238 tapOnFocusedWindow();
7239 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08007240 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
7241 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
7242 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007243
7244 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007245 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
7246 mFocusedWindow->getToken() == anrConnectionToken2);
7247 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
7248 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007249
7250 ASSERT_TRUE(mDispatcher->waitForIdle());
7251 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007252
7253 mFocusedWindow->consumeMotionDown();
7254 mFocusedWindow->consumeMotionUp();
7255 mUnfocusedWindow->consumeMotionOutside();
7256
Prabir Pradhanedd96402022-02-15 01:46:16 -08007257 sp<IBinder> responsiveToken1, responsiveToken2;
7258 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
7259 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007260
7261 // Both applications should be marked as responsive, in any order
7262 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
7263 mFocusedWindow->getToken() == responsiveToken2);
7264 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
7265 mUnfocusedWindow->getToken() == responsiveToken2);
7266 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007267}
7268
7269// If a window is already not responding, the second tap on the same window should be ignored.
7270// We should also log an error to account for the dropped event (not tested here).
7271// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7272TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7273 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007274 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007275 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007276 // Receive the events, but don't respond
7277 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7278 ASSERT_TRUE(downEventSequenceNum);
7279 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7280 ASSERT_TRUE(upEventSequenceNum);
7281 const std::chrono::duration timeout =
7282 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007283 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007284
7285 // Tap once again
7286 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007287 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007288 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7289 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007290 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007291 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7292 FOCUSED_WINDOW_LOCATION));
7293 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7294 // valid touch target
7295 mUnfocusedWindow->assertNoEvents();
7296
7297 // Consume the first tap
7298 mFocusedWindow->finishEvent(*downEventSequenceNum);
7299 mFocusedWindow->finishEvent(*upEventSequenceNum);
7300 ASSERT_TRUE(mDispatcher->waitForIdle());
7301 // The second tap did not go to the focused window
7302 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007303 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007304 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7305 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007306 mFakePolicy->assertNotifyAnrWasNotCalled();
7307}
7308
7309// If you tap outside of all windows, there will not be ANR
7310TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007311 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007312 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7313 LOCATION_OUTSIDE_ALL_WINDOWS));
7314 ASSERT_TRUE(mDispatcher->waitForIdle());
7315 mFakePolicy->assertNotifyAnrWasNotCalled();
7316}
7317
7318// Since the focused window is paused, tapping on it should not produce any events
7319TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7320 mFocusedWindow->setPaused(true);
7321 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7322
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007323 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007324 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7325 FOCUSED_WINDOW_LOCATION));
7326
7327 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7328 ASSERT_TRUE(mDispatcher->waitForIdle());
7329 // Should not ANR because the window is paused, and touches shouldn't go to it
7330 mFakePolicy->assertNotifyAnrWasNotCalled();
7331
7332 mFocusedWindow->assertNoEvents();
7333 mUnfocusedWindow->assertNoEvents();
7334}
7335
7336/**
7337 * If a window is processing a motion event, and then a key event comes in, the key event should
7338 * not to to the focused window until the motion is processed.
7339 * If a different window becomes focused at this time, the key should go to that window instead.
7340 *
7341 * Warning!!!
7342 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7343 * and the injection timeout that we specify when injecting the key.
7344 * We must have the injection timeout (10ms) be smaller than
7345 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7346 *
7347 * If that value changes, this test should also change.
7348 */
7349TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7350 // Set a long ANR timeout to prevent it from triggering
7351 mFocusedWindow->setDispatchingTimeout(2s);
7352 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7353
7354 tapOnUnfocusedWindow();
7355 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7356 ASSERT_TRUE(downSequenceNum);
7357 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7358 ASSERT_TRUE(upSequenceNum);
7359 // Don't finish the events yet, and send a key
7360 // Injection will succeed because we will eventually give up and send the key to the focused
7361 // window even if motions are still being processed.
7362
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007363 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007364 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7365 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007367 // Key will not be sent to the window, yet, because the window is still processing events
7368 // and the key remains pending, waiting for the touch events to be processed
7369 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7370 ASSERT_FALSE(keySequenceNum);
7371
7372 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007373 mFocusedWindow->setFocusable(false);
7374 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007375 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007376 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007377
7378 // Focus events should precede the key events
7379 mUnfocusedWindow->consumeFocusEvent(true);
7380 mFocusedWindow->consumeFocusEvent(false);
7381
7382 // Finish the tap events, which should unblock dispatcher
7383 mUnfocusedWindow->finishEvent(*downSequenceNum);
7384 mUnfocusedWindow->finishEvent(*upSequenceNum);
7385
7386 // Now that all queues are cleared and no backlog in the connections, the key event
7387 // can finally go to the newly focused "mUnfocusedWindow".
7388 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7389 mFocusedWindow->assertNoEvents();
7390 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007391 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007392}
7393
7394// When the touch stream is split across 2 windows, and one of them does not respond,
7395// then ANR should be raised and the touch should be canceled for the unresponsive window.
7396// The other window should not be affected by that.
7397TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7398 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007399 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7400 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7401 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007402 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007403 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007404
7405 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007406 mDispatcher->notifyMotion(
7407 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7408 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007409
7410 const std::chrono::duration timeout =
7411 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007412 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007413
7414 mUnfocusedWindow->consumeMotionDown();
7415 mFocusedWindow->consumeMotionDown();
7416 // Focused window may or may not receive ACTION_MOVE
7417 // But it should definitely receive ACTION_CANCEL due to the ANR
7418 InputEvent* event;
7419 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7420 ASSERT_TRUE(moveOrCancelSequenceNum);
7421 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7422 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007423 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007424 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7425 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7426 mFocusedWindow->consumeMotionCancel();
7427 } else {
7428 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7429 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007430 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007431 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7432 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007433
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007434 mUnfocusedWindow->assertNoEvents();
7435 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007436 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007437}
7438
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007439/**
7440 * If we have no focused window, and a key comes in, we start the ANR timer.
7441 * The focused application should add a focused window before the timer runs out to prevent ANR.
7442 *
7443 * If the user touches another application during this time, the key should be dropped.
7444 * Next, if a new focused window comes in, without toggling the focused application,
7445 * then no ANR should occur.
7446 *
7447 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7448 * but in some cases the policy may not update the focused application.
7449 */
7450TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7451 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7452 std::make_shared<FakeApplicationHandle>();
7453 focusedApplication->setDispatchingTimeout(60ms);
7454 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7455 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7456 mFocusedWindow->setFocusable(false);
7457
7458 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7459 mFocusedWindow->consumeFocusEvent(false);
7460
7461 // Send a key. The ANR timer should start because there is no focused window.
7462 // 'focusedApplication' will get blamed if this timer completes.
7463 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007464 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007465 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7466 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
7467 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007468 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007469
7470 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7471 // then the injected touches won't cause the focused event to get dropped.
7472 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7473 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7474 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7475 // For this test, it means that the key would get delivered to the window once it becomes
7476 // focused.
7477 std::this_thread::sleep_for(10ms);
7478
7479 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007480 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7481 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7482 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007483
7484 // We do not consume the motion right away, because that would require dispatcher to first
7485 // process (== drop) the key event, and by that time, ANR will be raised.
7486 // Set the focused window first.
7487 mFocusedWindow->setFocusable(true);
7488 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7489 setFocusedWindow(mFocusedWindow);
7490 mFocusedWindow->consumeFocusEvent(true);
7491 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7492 // to another application. This could be a bug / behaviour in the policy.
7493
7494 mUnfocusedWindow->consumeMotionDown();
7495
7496 ASSERT_TRUE(mDispatcher->waitForIdle());
7497 // Should not ANR because we actually have a focused window. It was just added too slowly.
7498 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7499}
7500
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007501// These tests ensure we cannot send touch events to a window that's positioned behind a window
7502// that has feature NO_INPUT_CHANNEL.
7503// Layout:
7504// Top (closest to user)
7505// mNoInputWindow (above all windows)
7506// mBottomWindow
7507// Bottom (furthest from user)
7508class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7509 virtual void SetUp() override {
7510 InputDispatcherTest::SetUp();
7511
7512 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007513 mNoInputWindow =
7514 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7515 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007516 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007517 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007518 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7519 // It's perfectly valid for this window to not have an associated input channel
7520
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007521 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7522 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007523 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7524
7525 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7526 }
7527
7528protected:
7529 std::shared_ptr<FakeApplicationHandle> mApplication;
7530 sp<FakeWindowHandle> mNoInputWindow;
7531 sp<FakeWindowHandle> mBottomWindow;
7532};
7533
7534TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7535 PointF touchedPoint = {10, 10};
7536
Prabir Pradhan678438e2023-04-13 19:32:51 +00007537 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7538 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7539 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007540
7541 mNoInputWindow->assertNoEvents();
7542 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7543 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7544 // and therefore should prevent mBottomWindow from receiving touches
7545 mBottomWindow->assertNoEvents();
7546}
7547
7548/**
7549 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7550 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7551 */
7552TEST_F(InputDispatcherMultiWindowOcclusionTests,
7553 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007554 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7555 "Window with input channel and NO_INPUT_CHANNEL",
7556 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007557
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007558 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007559 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7560 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7561
7562 PointF touchedPoint = {10, 10};
7563
Prabir Pradhan678438e2023-04-13 19:32:51 +00007564 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7565 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7566 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007567
7568 mNoInputWindow->assertNoEvents();
7569 mBottomWindow->assertNoEvents();
7570}
7571
Vishnu Nair958da932020-08-21 17:12:37 -07007572class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7573protected:
7574 std::shared_ptr<FakeApplicationHandle> mApp;
7575 sp<FakeWindowHandle> mWindow;
7576 sp<FakeWindowHandle> mMirror;
7577
7578 virtual void SetUp() override {
7579 InputDispatcherTest::SetUp();
7580 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007581 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7582 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7583 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007584 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7585 mWindow->setFocusable(true);
7586 mMirror->setFocusable(true);
7587 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7588 }
7589};
7590
7591TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7592 // Request focus on a mirrored window
7593 setFocusedWindow(mMirror);
7594
7595 // window gets focused
7596 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7598 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007599 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7600}
7601
7602// A focused & mirrored window remains focused only if the window and its mirror are both
7603// focusable.
7604TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7605 setFocusedWindow(mMirror);
7606
7607 // window gets focused
7608 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7610 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007611 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007612 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7613 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007614 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7615
7616 mMirror->setFocusable(false);
7617 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7618
7619 // window loses focus since one of the windows associated with the token in not focusable
7620 mWindow->consumeFocusEvent(false);
7621
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007622 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7623 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007624 mWindow->assertNoEvents();
7625}
7626
7627// A focused & mirrored window remains focused until the window and its mirror both become
7628// invisible.
7629TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7630 setFocusedWindow(mMirror);
7631
7632 // window gets focused
7633 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7635 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007636 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007637 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7638 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007639 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7640
7641 mMirror->setVisible(false);
7642 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7643
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7645 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007646 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7648 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007649 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7650
7651 mWindow->setVisible(false);
7652 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7653
7654 // window loses focus only after all windows associated with the token become invisible.
7655 mWindow->consumeFocusEvent(false);
7656
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007657 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7658 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007659 mWindow->assertNoEvents();
7660}
7661
7662// A focused & mirrored window remains focused until both windows are removed.
7663TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7664 setFocusedWindow(mMirror);
7665
7666 // window gets focused
7667 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007668 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7669 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007670 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007671 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7672 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007673 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7674
7675 // single window is removed but the window token remains focused
7676 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7677
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7679 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007680 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007681 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7682 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007683 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7684
7685 // Both windows are removed
7686 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7687 mWindow->consumeFocusEvent(false);
7688
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007689 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7690 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007691 mWindow->assertNoEvents();
7692}
7693
7694// Focus request can be pending until one window becomes visible.
7695TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7696 // Request focus on an invisible mirror.
7697 mWindow->setVisible(false);
7698 mMirror->setVisible(false);
7699 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7700 setFocusedWindow(mMirror);
7701
7702 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007703 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007704 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7705 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007706
7707 mMirror->setVisible(true);
7708 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7709
7710 // window gets focused
7711 mWindow->consumeFocusEvent(true);
7712 // window gets the pending key event
7713 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7714}
Prabir Pradhan99987712020-11-10 18:43:05 -08007715
7716class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7717protected:
7718 std::shared_ptr<FakeApplicationHandle> mApp;
7719 sp<FakeWindowHandle> mWindow;
7720 sp<FakeWindowHandle> mSecondWindow;
7721
7722 void SetUp() override {
7723 InputDispatcherTest::SetUp();
7724 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007725 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007726 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007727 mSecondWindow =
7728 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007729 mSecondWindow->setFocusable(true);
7730
7731 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7732 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7733
7734 setFocusedWindow(mWindow);
7735 mWindow->consumeFocusEvent(true);
7736 }
7737
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007738 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007739 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007740 }
7741
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007742 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7743 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007744 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007745 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7746 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007747 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007748 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007749 }
7750};
7751
7752TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7753 // Ensure that capture cannot be obtained for unfocused windows.
7754 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7755 mFakePolicy->assertSetPointerCaptureNotCalled();
7756 mSecondWindow->assertNoEvents();
7757
7758 // Ensure that capture can be enabled from the focus window.
7759 requestAndVerifyPointerCapture(mWindow, true);
7760
7761 // Ensure that capture cannot be disabled from a window that does not have capture.
7762 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7763 mFakePolicy->assertSetPointerCaptureNotCalled();
7764
7765 // Ensure that capture can be disabled from the window with capture.
7766 requestAndVerifyPointerCapture(mWindow, false);
7767}
7768
7769TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007770 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007771
7772 setFocusedWindow(mSecondWindow);
7773
7774 // Ensure that the capture disabled event was sent first.
7775 mWindow->consumeCaptureEvent(false);
7776 mWindow->consumeFocusEvent(false);
7777 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007778 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007779
7780 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007781 notifyPointerCaptureChanged({});
7782 notifyPointerCaptureChanged(request);
7783 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007784 mWindow->assertNoEvents();
7785 mSecondWindow->assertNoEvents();
7786 mFakePolicy->assertSetPointerCaptureNotCalled();
7787}
7788
7789TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007790 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007791
7792 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007793 notifyPointerCaptureChanged({});
7794 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007795
7796 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007797 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007798 mWindow->consumeCaptureEvent(false);
7799 mWindow->assertNoEvents();
7800}
7801
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007802TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7803 requestAndVerifyPointerCapture(mWindow, true);
7804
7805 // The first window loses focus.
7806 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007807 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007808 mWindow->consumeCaptureEvent(false);
7809
7810 // Request Pointer Capture from the second window before the notification from InputReader
7811 // arrives.
7812 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007813 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007814
7815 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007816 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007817
7818 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007819 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007820
7821 mSecondWindow->consumeFocusEvent(true);
7822 mSecondWindow->consumeCaptureEvent(true);
7823}
7824
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007825TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7826 // App repeatedly enables and disables capture.
7827 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7828 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7829 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7830 mFakePolicy->assertSetPointerCaptureCalled(false);
7831 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7832 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7833
7834 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7835 // first request is now stale, this should do nothing.
7836 notifyPointerCaptureChanged(firstRequest);
7837 mWindow->assertNoEvents();
7838
7839 // InputReader notifies that the second request was enabled.
7840 notifyPointerCaptureChanged(secondRequest);
7841 mWindow->consumeCaptureEvent(true);
7842}
7843
Prabir Pradhan7092e262022-05-03 16:51:09 +00007844TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7845 requestAndVerifyPointerCapture(mWindow, true);
7846
7847 // App toggles pointer capture off and on.
7848 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7849 mFakePolicy->assertSetPointerCaptureCalled(false);
7850
7851 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7852 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7853
7854 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7855 // preceding "disable" request.
7856 notifyPointerCaptureChanged(enableRequest);
7857
7858 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7859 // any notifications.
7860 mWindow->assertNoEvents();
7861}
7862
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007863class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7864protected:
7865 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007866
7867 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7868 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7869
7870 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7871 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7872
7873 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7874 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7875 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7876 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7877 MAXIMUM_OBSCURING_OPACITY);
7878
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007879 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007880 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007881 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007882
7883 sp<FakeWindowHandle> mTouchWindow;
7884
7885 virtual void SetUp() override {
7886 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007887 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007888 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7889 }
7890
7891 virtual void TearDown() override {
7892 InputDispatcherTest::TearDown();
7893 mTouchWindow.clear();
7894 }
7895
chaviw3277faf2021-05-19 16:45:23 -05007896 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
7897 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007898 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007899 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007900 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007901 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007902 return window;
7903 }
7904
7905 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
7906 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7907 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007908 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007909 // Generate an arbitrary PID based on the UID
7910 window->setOwnerInfo(1777 + (uid % 10000), uid);
7911 return window;
7912 }
7913
7914 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007915 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7916 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7917 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007918 }
7919};
7920
7921TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007922 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007923 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007924 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007925
7926 touch();
7927
7928 mTouchWindow->assertNoEvents();
7929}
7930
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007931TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007932 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7933 const sp<FakeWindowHandle>& w =
7934 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7935 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7936
7937 touch();
7938
7939 mTouchWindow->assertNoEvents();
7940}
7941
7942TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007943 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7944 const sp<FakeWindowHandle>& w =
7945 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7946 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7947
7948 touch();
7949
7950 w->assertNoEvents();
7951}
7952
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007953TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007954 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7955 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007956
7957 touch();
7958
7959 mTouchWindow->consumeAnyMotionDown();
7960}
7961
7962TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007963 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007964 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007965 w->setFrame(Rect(0, 0, 50, 50));
7966 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007967
7968 touch({PointF{100, 100}});
7969
7970 mTouchWindow->consumeAnyMotionDown();
7971}
7972
7973TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007974 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007975 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007976 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7977
7978 touch();
7979
7980 mTouchWindow->consumeAnyMotionDown();
7981}
7982
7983TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7984 const sp<FakeWindowHandle>& w =
7985 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7986 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007987
7988 touch();
7989
7990 mTouchWindow->consumeAnyMotionDown();
7991}
7992
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007993TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7994 const sp<FakeWindowHandle>& w =
7995 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7996 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7997
7998 touch();
7999
8000 w->assertNoEvents();
8001}
8002
8003/**
8004 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8005 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8006 * window, the occluding window will still receive ACTION_OUTSIDE event.
8007 */
8008TEST_F(InputDispatcherUntrustedTouchesTest,
8009 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8010 const sp<FakeWindowHandle>& w =
8011 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008012 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008013 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8014
8015 touch();
8016
8017 w->consumeMotionOutside();
8018}
8019
8020TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8021 const sp<FakeWindowHandle>& w =
8022 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008023 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008024 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8025
8026 touch();
8027
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008028 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008029}
8030
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008031TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008032 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008033 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8034 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008035 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8036
8037 touch();
8038
8039 mTouchWindow->consumeAnyMotionDown();
8040}
8041
8042TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8043 const sp<FakeWindowHandle>& w =
8044 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8045 MAXIMUM_OBSCURING_OPACITY);
8046 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008047
8048 touch();
8049
8050 mTouchWindow->consumeAnyMotionDown();
8051}
8052
8053TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008054 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008055 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8056 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008057 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8058
8059 touch();
8060
8061 mTouchWindow->assertNoEvents();
8062}
8063
8064TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8065 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8066 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008067 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8068 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008069 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008070 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8071 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008072 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8073
8074 touch();
8075
8076 mTouchWindow->assertNoEvents();
8077}
8078
8079TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8080 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8081 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008082 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8083 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008084 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008085 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8086 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008087 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8088
8089 touch();
8090
8091 mTouchWindow->consumeAnyMotionDown();
8092}
8093
8094TEST_F(InputDispatcherUntrustedTouchesTest,
8095 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8096 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008097 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8098 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008099 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008100 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8101 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008102 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8103
8104 touch();
8105
8106 mTouchWindow->consumeAnyMotionDown();
8107}
8108
8109TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8110 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008111 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8112 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008113 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008114 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8115 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008116 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008117
8118 touch();
8119
8120 mTouchWindow->assertNoEvents();
8121}
8122
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008123TEST_F(InputDispatcherUntrustedTouchesTest,
8124 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8125 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008126 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8127 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008128 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008129 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8130 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008131 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8132
8133 touch();
8134
8135 mTouchWindow->assertNoEvents();
8136}
8137
8138TEST_F(InputDispatcherUntrustedTouchesTest,
8139 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8140 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008141 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8142 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008143 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008144 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8145 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008146 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8147
8148 touch();
8149
8150 mTouchWindow->consumeAnyMotionDown();
8151}
8152
8153TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8154 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008155 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8156 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008157 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8158
8159 touch();
8160
8161 mTouchWindow->consumeAnyMotionDown();
8162}
8163
8164TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8165 const sp<FakeWindowHandle>& w =
8166 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
8167 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8168
8169 touch();
8170
8171 mTouchWindow->consumeAnyMotionDown();
8172}
8173
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008174TEST_F(InputDispatcherUntrustedTouchesTest,
8175 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8176 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8177 const sp<FakeWindowHandle>& w =
8178 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
8179 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8180
8181 touch();
8182
8183 mTouchWindow->assertNoEvents();
8184}
8185
8186TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8187 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8188 const sp<FakeWindowHandle>& w =
8189 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
8190 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8191
8192 touch();
8193
8194 mTouchWindow->consumeAnyMotionDown();
8195}
8196
8197TEST_F(InputDispatcherUntrustedTouchesTest,
8198 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8199 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8200 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008201 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8202 OPACITY_ABOVE_THRESHOLD);
8203 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8204
8205 touch();
8206
8207 mTouchWindow->consumeAnyMotionDown();
8208}
8209
8210TEST_F(InputDispatcherUntrustedTouchesTest,
8211 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8212 const sp<FakeWindowHandle>& w1 =
8213 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8214 OPACITY_BELOW_THRESHOLD);
8215 const sp<FakeWindowHandle>& w2 =
8216 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8217 OPACITY_BELOW_THRESHOLD);
8218 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8219
8220 touch();
8221
8222 mTouchWindow->assertNoEvents();
8223}
8224
8225/**
8226 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8227 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8228 * (which alone would result in allowing touches) does not affect the blocking behavior.
8229 */
8230TEST_F(InputDispatcherUntrustedTouchesTest,
8231 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8232 const sp<FakeWindowHandle>& wB =
8233 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8234 OPACITY_BELOW_THRESHOLD);
8235 const sp<FakeWindowHandle>& wC =
8236 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8237 OPACITY_BELOW_THRESHOLD);
8238 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8239
8240 touch();
8241
8242 mTouchWindow->assertNoEvents();
8243}
8244
8245/**
8246 * This test is testing that a window from a different UID but with same application token doesn't
8247 * block the touch. Apps can share the application token for close UI collaboration for example.
8248 */
8249TEST_F(InputDispatcherUntrustedTouchesTest,
8250 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8251 const sp<FakeWindowHandle>& w =
8252 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8253 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008254 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8255
8256 touch();
8257
8258 mTouchWindow->consumeAnyMotionDown();
8259}
8260
arthurhungb89ccb02020-12-30 16:19:01 +08008261class InputDispatcherDragTests : public InputDispatcherTest {
8262protected:
8263 std::shared_ptr<FakeApplicationHandle> mApp;
8264 sp<FakeWindowHandle> mWindow;
8265 sp<FakeWindowHandle> mSecondWindow;
8266 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008267 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008268 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8269 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008270
8271 void SetUp() override {
8272 InputDispatcherTest::SetUp();
8273 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008274 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008275 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008276
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008277 mSecondWindow =
8278 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008279 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008280
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008281 mSpyWindow =
8282 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008283 mSpyWindow->setSpy(true);
8284 mSpyWindow->setTrustedOverlay(true);
8285 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8286
arthurhungb89ccb02020-12-30 16:19:01 +08008287 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008288 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008289 }
8290
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008291 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8292 switch (fromSource) {
8293 case AINPUT_SOURCE_TOUCHSCREEN:
8294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8295 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8296 ADISPLAY_ID_DEFAULT, {50, 50}))
8297 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8298 break;
8299 case AINPUT_SOURCE_STYLUS:
8300 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8301 injectMotionEvent(
8302 mDispatcher,
8303 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8304 AINPUT_SOURCE_STYLUS)
8305 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008306 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008307 .x(50)
8308 .y(50))
8309 .build()));
8310 break;
8311 case AINPUT_SOURCE_MOUSE:
8312 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8313 injectMotionEvent(
8314 mDispatcher,
8315 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8316 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8317 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008318 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008319 .x(50)
8320 .y(50))
8321 .build()));
8322 break;
8323 default:
8324 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8325 }
arthurhungb89ccb02020-12-30 16:19:01 +08008326
8327 // Window should receive motion event.
8328 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008329 // Spy window should also receive motion event
8330 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008331 }
8332
8333 // Start performing drag, we will create a drag window and transfer touch to it.
8334 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8335 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008336 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008337 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008338 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008339 }
arthurhungb89ccb02020-12-30 16:19:01 +08008340
8341 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008342 mDragWindow =
8343 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008344 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08008345 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008346 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008347
8348 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008349 bool transferred =
8350 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008351 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008352 if (transferred) {
8353 mWindow->consumeMotionCancel();
8354 mDragWindow->consumeMotionDown();
8355 }
8356 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008357 }
8358};
8359
8360TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008361 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008362
8363 // Move on window.
8364 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8365 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8366 ADISPLAY_ID_DEFAULT, {50, 50}))
8367 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8368 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8369 mWindow->consumeDragEvent(false, 50, 50);
8370 mSecondWindow->assertNoEvents();
8371
8372 // Move to another window.
8373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8374 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8375 ADISPLAY_ID_DEFAULT, {150, 50}))
8376 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8377 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8378 mWindow->consumeDragEvent(true, 150, 50);
8379 mSecondWindow->consumeDragEvent(false, 50, 50);
8380
8381 // Move back to original window.
8382 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8383 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8384 ADISPLAY_ID_DEFAULT, {50, 50}))
8385 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8386 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8387 mWindow->consumeDragEvent(false, 50, 50);
8388 mSecondWindow->consumeDragEvent(true, -50, 50);
8389
8390 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8391 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8392 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8393 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8394 mWindow->assertNoEvents();
8395 mSecondWindow->assertNoEvents();
8396}
8397
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008398TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008399 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008400
8401 // No cancel event after drag start
8402 mSpyWindow->assertNoEvents();
8403
8404 const MotionEvent secondFingerDownEvent =
8405 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8406 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008407 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8408 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008409 .build();
8410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8411 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8412 InputEventInjectionSync::WAIT_FOR_RESULT))
8413 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8414
8415 // Receives cancel for first pointer after next pointer down
8416 mSpyWindow->consumeMotionCancel();
8417 mSpyWindow->consumeMotionDown();
8418
8419 mSpyWindow->assertNoEvents();
8420}
8421
arthurhungf452d0b2021-01-06 00:19:52 +08008422TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008423 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008424
8425 // Move on window.
8426 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8427 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8428 ADISPLAY_ID_DEFAULT, {50, 50}))
8429 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8430 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8431 mWindow->consumeDragEvent(false, 50, 50);
8432 mSecondWindow->assertNoEvents();
8433
8434 // Move to another window.
8435 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8436 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8437 ADISPLAY_ID_DEFAULT, {150, 50}))
8438 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8439 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8440 mWindow->consumeDragEvent(true, 150, 50);
8441 mSecondWindow->consumeDragEvent(false, 50, 50);
8442
8443 // drop to another window.
8444 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8445 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8446 {150, 50}))
8447 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8448 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8449 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8450 mWindow->assertNoEvents();
8451 mSecondWindow->assertNoEvents();
8452}
8453
arthurhung6d4bed92021-03-17 11:59:33 +08008454TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008455 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008456
8457 // Move on window and keep button pressed.
8458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8459 injectMotionEvent(mDispatcher,
8460 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8461 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008462 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008463 .build()))
8464 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8465 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8466 mWindow->consumeDragEvent(false, 50, 50);
8467 mSecondWindow->assertNoEvents();
8468
8469 // Move to another window and release button, expect to drop item.
8470 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8471 injectMotionEvent(mDispatcher,
8472 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8473 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008474 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008475 .build()))
8476 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8477 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8478 mWindow->assertNoEvents();
8479 mSecondWindow->assertNoEvents();
8480 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8481
8482 // nothing to the window.
8483 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8484 injectMotionEvent(mDispatcher,
8485 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8486 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008487 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008488 .build()))
8489 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8490 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8491 mWindow->assertNoEvents();
8492 mSecondWindow->assertNoEvents();
8493}
8494
Arthur Hung54745652022-04-20 07:17:41 +00008495TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008496 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008497
8498 // Set second window invisible.
8499 mSecondWindow->setVisible(false);
8500 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8501
8502 // Move on window.
8503 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8504 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8505 ADISPLAY_ID_DEFAULT, {50, 50}))
8506 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8507 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8508 mWindow->consumeDragEvent(false, 50, 50);
8509 mSecondWindow->assertNoEvents();
8510
8511 // Move to another window.
8512 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8513 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8514 ADISPLAY_ID_DEFAULT, {150, 50}))
8515 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8516 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8517 mWindow->consumeDragEvent(true, 150, 50);
8518 mSecondWindow->assertNoEvents();
8519
8520 // drop to another window.
8521 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8522 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8523 {150, 50}))
8524 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8525 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8526 mFakePolicy->assertDropTargetEquals(nullptr);
8527 mWindow->assertNoEvents();
8528 mSecondWindow->assertNoEvents();
8529}
8530
Arthur Hung54745652022-04-20 07:17:41 +00008531TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008532 // Ensure window could track pointerIds if it didn't support split touch.
8533 mWindow->setPreventSplitting(true);
8534
Arthur Hung54745652022-04-20 07:17:41 +00008535 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8536 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8537 {50, 50}))
8538 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8539 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8540
8541 const MotionEvent secondFingerDownEvent =
8542 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8543 .displayId(ADISPLAY_ID_DEFAULT)
8544 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008545 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8546 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008547 .build();
8548 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8549 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8550 InputEventInjectionSync::WAIT_FOR_RESULT))
8551 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008552 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008553
8554 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008555 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008556}
8557
8558TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8559 // First down on second window.
8560 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8561 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8562 {150, 50}))
8563 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8564
8565 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8566
8567 // Second down on first window.
8568 const MotionEvent secondFingerDownEvent =
8569 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8570 .displayId(ADISPLAY_ID_DEFAULT)
8571 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008572 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8573 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008574 .build();
8575 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8576 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8577 InputEventInjectionSync::WAIT_FOR_RESULT))
8578 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8579 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8580
8581 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008582 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008583
8584 // Move on window.
8585 const MotionEvent secondFingerMoveEvent =
8586 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8587 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008588 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8589 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008590 .build();
8591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8592 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8593 InputEventInjectionSync::WAIT_FOR_RESULT));
8594 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8595 mWindow->consumeDragEvent(false, 50, 50);
8596 mSecondWindow->consumeMotionMove();
8597
8598 // Release the drag pointer should perform drop.
8599 const MotionEvent secondFingerUpEvent =
8600 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8601 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008602 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8603 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008604 .build();
8605 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8606 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8607 InputEventInjectionSync::WAIT_FOR_RESULT));
8608 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8609 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
8610 mWindow->assertNoEvents();
8611 mSecondWindow->consumeMotionMove();
8612}
8613
Arthur Hung3915c1f2022-05-31 07:17:17 +00008614TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008615 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008616
8617 // Update window of second display.
8618 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008619 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008620 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8621
8622 // Let second display has a touch state.
8623 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8624 injectMotionEvent(mDispatcher,
8625 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8626 AINPUT_SOURCE_TOUCHSCREEN)
8627 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008628 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008629 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008630 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008631 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008632 // Update window again.
8633 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8634
8635 // Move on window.
8636 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8637 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8638 ADISPLAY_ID_DEFAULT, {50, 50}))
8639 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8640 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8641 mWindow->consumeDragEvent(false, 50, 50);
8642 mSecondWindow->assertNoEvents();
8643
8644 // Move to another window.
8645 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8646 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8647 ADISPLAY_ID_DEFAULT, {150, 50}))
8648 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8649 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8650 mWindow->consumeDragEvent(true, 150, 50);
8651 mSecondWindow->consumeDragEvent(false, 50, 50);
8652
8653 // drop to another window.
8654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8655 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8656 {150, 50}))
8657 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8658 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8659 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8660 mWindow->assertNoEvents();
8661 mSecondWindow->assertNoEvents();
8662}
8663
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008664TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8665 startDrag(true, AINPUT_SOURCE_MOUSE);
8666 // Move on window.
8667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8668 injectMotionEvent(mDispatcher,
8669 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8670 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8671 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008672 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008673 .x(50)
8674 .y(50))
8675 .build()))
8676 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8677 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8678 mWindow->consumeDragEvent(false, 50, 50);
8679 mSecondWindow->assertNoEvents();
8680
8681 // Move to another window.
8682 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8683 injectMotionEvent(mDispatcher,
8684 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8685 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8686 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008687 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008688 .x(150)
8689 .y(50))
8690 .build()))
8691 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8692 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8693 mWindow->consumeDragEvent(true, 150, 50);
8694 mSecondWindow->consumeDragEvent(false, 50, 50);
8695
8696 // drop to another window.
8697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8698 injectMotionEvent(mDispatcher,
8699 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8700 .buttonState(0)
8701 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008702 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008703 .x(150)
8704 .y(50))
8705 .build()))
8706 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8707 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8708 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8709 mWindow->assertNoEvents();
8710 mSecondWindow->assertNoEvents();
8711}
8712
Vishnu Nair062a8672021-09-03 16:07:44 -07008713class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8714
8715TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8716 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008717 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8718 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008719 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008720 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8721 window->setFocusable(true);
8722 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8723 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008724 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008725
8726 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008727 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008728 window->assertNoEvents();
8729
Prabir Pradhan678438e2023-04-13 19:32:51 +00008730 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8731 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008732 window->assertNoEvents();
8733
8734 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008735 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008736 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8737
Prabir Pradhan678438e2023-04-13 19:32:51 +00008738 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008739 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8740
Prabir Pradhan678438e2023-04-13 19:32:51 +00008741 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8742 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008743 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8744 window->assertNoEvents();
8745}
8746
8747TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8748 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8749 std::make_shared<FakeApplicationHandle>();
8750 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008751 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8752 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008753 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8754 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008755 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008756 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008757 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8758 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008759 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008760 window->setOwnerInfo(222, 222);
8761 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8762 window->setFocusable(true);
8763 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8764 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008765 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008766
8767 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008768 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008769 window->assertNoEvents();
8770
Prabir Pradhan678438e2023-04-13 19:32:51 +00008771 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8772 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008773 window->assertNoEvents();
8774
8775 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008776 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008777 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8778
Prabir Pradhan678438e2023-04-13 19:32:51 +00008779 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008780 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8781
Prabir Pradhan678438e2023-04-13 19:32:51 +00008782 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8783 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008784 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8785 window->assertNoEvents();
8786}
8787
8788TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8789 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8790 std::make_shared<FakeApplicationHandle>();
8791 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008792 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8793 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008794 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8795 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008796 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008797 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008798 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8799 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008800 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008801 window->setOwnerInfo(222, 222);
8802 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8803 window->setFocusable(true);
8804 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8805 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008806 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008807
8808 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008809 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008810 window->assertNoEvents();
8811
Prabir Pradhan678438e2023-04-13 19:32:51 +00008812 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8813 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008814 window->assertNoEvents();
8815
8816 // When the window is no longer obscured because it went on top, it should get input
8817 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8818
Prabir Pradhan678438e2023-04-13 19:32:51 +00008819 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008820 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8821
Prabir Pradhan678438e2023-04-13 19:32:51 +00008822 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8823 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008824 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8825 window->assertNoEvents();
8826}
8827
Antonio Kantekf16f2832021-09-28 04:39:20 +00008828class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8829protected:
8830 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008831 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008832 sp<FakeWindowHandle> mWindow;
8833 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008834 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008835
8836 void SetUp() override {
8837 InputDispatcherTest::SetUp();
8838
8839 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008840 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008841 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008842 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008843 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008844 mSecondWindow =
8845 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008846 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008847 mThirdWindow =
8848 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8849 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8850 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008851
8852 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008853 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8854 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8855 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008856 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008857
Antonio Kantek15beb512022-06-13 22:35:41 +00008858 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008859 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008860 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008861 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8862 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008863 mThirdWindow->assertNoEvents();
8864 }
8865
8866 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8867 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008868 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008869 SECOND_DISPLAY_ID)) {
8870 mWindow->assertNoEvents();
8871 mSecondWindow->assertNoEvents();
8872 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008873 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008874 }
8875
Antonio Kantek15beb512022-06-13 22:35:41 +00008876 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid,
8877 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008878 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8879 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008880 mWindow->consumeTouchModeEvent(inTouchMode);
8881 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008882 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008883 }
8884};
8885
Antonio Kantek26defcf2022-02-08 01:12:27 +00008886TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008887 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008888 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8889 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008890 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008891}
8892
Antonio Kantek26defcf2022-02-08 01:12:27 +00008893TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8894 const WindowInfo& windowInfo = *mWindow->getInfo();
8895 int32_t ownerPid = windowInfo.ownerPid;
8896 int32_t ownerUid = windowInfo.ownerUid;
8897 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
8898 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008899 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008900 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008901 mWindow->assertNoEvents();
8902 mSecondWindow->assertNoEvents();
8903}
8904
8905TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8906 const WindowInfo& windowInfo = *mWindow->getInfo();
8907 int32_t ownerPid = windowInfo.ownerPid;
8908 int32_t ownerUid = windowInfo.ownerUid;
8909 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
Antonio Kantek15beb512022-06-13 22:35:41 +00008910 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008911 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008912}
8913
Antonio Kantekf16f2832021-09-28 04:39:20 +00008914TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008915 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008916 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8917 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008918 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008919 mWindow->assertNoEvents();
8920 mSecondWindow->assertNoEvents();
8921}
8922
Antonio Kantek15beb512022-06-13 22:35:41 +00008923TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8924 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8925 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8926 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008927 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008928 mWindow->assertNoEvents();
8929 mSecondWindow->assertNoEvents();
8930 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8931}
8932
Antonio Kantek48710e42022-03-24 14:19:30 -07008933TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8934 // Interact with the window first.
8935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8936 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8937 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8938
8939 // Then remove focus.
8940 mWindow->setFocusable(false);
8941 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8942
8943 // Assert that caller can switch touch mode by owning one of the last interacted window.
8944 const WindowInfo& windowInfo = *mWindow->getInfo();
8945 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8946 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008947 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008948}
8949
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008950class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8951public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008952 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008953 std::shared_ptr<FakeApplicationHandle> application =
8954 std::make_shared<FakeApplicationHandle>();
8955 std::string name = "Fake Spy ";
8956 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008957 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8958 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008959 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008960 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008961 return spy;
8962 }
8963
8964 sp<FakeWindowHandle> createForeground() {
8965 std::shared_ptr<FakeApplicationHandle> application =
8966 std::make_shared<FakeApplicationHandle>();
8967 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008968 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8969 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008970 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008971 return window;
8972 }
8973
8974private:
8975 int mSpyCount{0};
8976};
8977
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008978using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008979/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008980 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8981 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008982TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8983 ScopedSilentDeath _silentDeath;
8984
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008985 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008986 spy->setTrustedOverlay(false);
8987 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8988 ".* not a trusted overlay");
8989}
8990
8991/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008992 * Input injection into a display with a spy window but no foreground windows should succeed.
8993 */
8994TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008995 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008996 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
8997
8998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8999 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9000 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9001 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9002}
9003
9004/**
9005 * Verify the order in which different input windows receive events. The touched foreground window
9006 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9007 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9008 * receive events before ones belows it.
9009 *
9010 * Here, we set up a scenario with four windows in the following Z order from the top:
9011 * spy1, spy2, window, spy3.
9012 * We then inject an event and verify that the foreground "window" receives it first, followed by
9013 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9014 * window.
9015 */
9016TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9017 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009018 auto spy1 = createSpy();
9019 auto spy2 = createSpy();
9020 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009021 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
9022 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9023 const size_t numChannels = channels.size();
9024
Michael Wright8e9a8562022-02-09 13:44:29 +00009025 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009026 if (!epollFd.ok()) {
9027 FAIL() << "Failed to create epoll fd";
9028 }
9029
9030 for (size_t i = 0; i < numChannels; i++) {
9031 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9032 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9033 FAIL() << "Failed to add fd to epoll";
9034 }
9035 }
9036
9037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9038 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9039 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9040
9041 std::vector<size_t> eventOrder;
9042 std::vector<struct epoll_event> events(numChannels);
9043 for (;;) {
9044 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9045 (100ms).count());
9046 if (nFds < 0) {
9047 FAIL() << "Failed to call epoll_wait";
9048 }
9049 if (nFds == 0) {
9050 break; // epoll_wait timed out
9051 }
9052 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009053 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009054 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009055 channels[i]->consumeMotionDown();
9056 }
9057 }
9058
9059 // Verify the order in which the events were received.
9060 EXPECT_EQ(3u, eventOrder.size());
9061 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9062 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9063 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9064}
9065
9066/**
9067 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9068 */
9069TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9070 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009071 auto spy = createSpy();
9072 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009073 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9074
9075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9076 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9077 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9078 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9079 spy->assertNoEvents();
9080}
9081
9082/**
9083 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9084 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9085 * to the window.
9086 */
9087TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9088 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009089 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009090 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
9091 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9092
9093 // Inject an event outside the spy window's touchable region.
9094 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9095 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9096 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9097 window->consumeMotionDown();
9098 spy->assertNoEvents();
9099 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9100 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9101 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9102 window->consumeMotionUp();
9103 spy->assertNoEvents();
9104
9105 // Inject an event inside the spy window's touchable region.
9106 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9107 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9108 {5, 10}))
9109 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9110 window->consumeMotionDown();
9111 spy->consumeMotionDown();
9112}
9113
9114/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009115 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009116 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009117 */
9118TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9119 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009120 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009121 auto spy = createSpy();
9122 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009123 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009124 spy->setFrame(Rect{0, 0, 20, 20});
9125 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9126
9127 // Inject an event outside the spy window's frame and touchable region.
9128 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009129 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9130 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009131 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9132 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009133 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009134}
9135
9136/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009137 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9138 * pointers that are down within its bounds.
9139 */
9140TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9141 auto windowLeft = createForeground();
9142 windowLeft->setFrame({0, 0, 100, 200});
9143 auto windowRight = createForeground();
9144 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009145 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009146 spy->setFrame({0, 0, 200, 200});
9147 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
9148
9149 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9150 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9151 {50, 50}))
9152 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9153 windowLeft->consumeMotionDown();
9154 spy->consumeMotionDown();
9155
9156 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009157 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009158 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009159 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9160 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009161 .build();
9162 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9163 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9164 InputEventInjectionSync::WAIT_FOR_RESULT))
9165 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9166 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009167 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009168}
9169
9170/**
9171 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9172 * the spy should receive the second pointer with ACTION_DOWN.
9173 */
9174TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9175 auto window = createForeground();
9176 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009177 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009178 spyRight->setFrame({100, 0, 200, 200});
9179 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
9180
9181 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9182 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9183 {50, 50}))
9184 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9185 window->consumeMotionDown();
9186 spyRight->assertNoEvents();
9187
9188 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009189 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009190 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009191 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9192 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009193 .build();
9194 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9195 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9196 InputEventInjectionSync::WAIT_FOR_RESULT))
9197 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009198 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009199 spyRight->consumeMotionDown();
9200}
9201
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009202/**
9203 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9204 * windows should be allowed to control split touch.
9205 */
9206TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009207 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009208 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009209 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009210 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009211
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009212 auto window = createForeground();
9213 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009214
9215 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9216
9217 // First finger down, no window touched.
9218 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9219 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9220 {100, 200}))
9221 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9222 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9223 window->assertNoEvents();
9224
9225 // Second finger down on window, the window should receive touch down.
9226 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009227 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009228 .displayId(ADISPLAY_ID_DEFAULT)
9229 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009230 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9231 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009232 .build();
9233 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9234 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9235 InputEventInjectionSync::WAIT_FOR_RESULT))
9236 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9237
9238 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009239 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009240}
9241
9242/**
9243 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9244 * do not receive key events.
9245 */
9246TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009247 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009248 spy->setFocusable(false);
9249
9250 auto window = createForeground();
9251 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9252 setFocusedWindow(window);
9253 window->consumeFocusEvent(true);
9254
9255 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
9256 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9257 window->consumeKeyDown(ADISPLAY_ID_NONE);
9258
9259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
9260 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9261 window->consumeKeyUp(ADISPLAY_ID_NONE);
9262
9263 spy->assertNoEvents();
9264}
9265
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009266using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9267
9268/**
9269 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9270 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9271 */
9272TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9273 auto window = createForeground();
9274 auto spy1 = createSpy();
9275 auto spy2 = createSpy();
9276 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
9277
9278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9279 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9280 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9281 window->consumeMotionDown();
9282 spy1->consumeMotionDown();
9283 spy2->consumeMotionDown();
9284
9285 // Pilfer pointers from the second spy window.
9286 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9287 spy2->assertNoEvents();
9288 spy1->consumeMotionCancel();
9289 window->consumeMotionCancel();
9290
9291 // The rest of the gesture should only be sent to the second spy window.
9292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9293 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9294 ADISPLAY_ID_DEFAULT))
9295 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9296 spy2->consumeMotionMove();
9297 spy1->assertNoEvents();
9298 window->assertNoEvents();
9299}
9300
9301/**
9302 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9303 * in the middle of the gesture.
9304 */
9305TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9306 auto window = createForeground();
9307 auto spy = createSpy();
9308 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9309
9310 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9311 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9312 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9313 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9314 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9315
9316 window->releaseChannel();
9317
9318 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9319
9320 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9321 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9322 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9323 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9324}
9325
9326/**
9327 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9328 * the spy, but not to any other windows.
9329 */
9330TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9331 auto spy = createSpy();
9332 auto window = createForeground();
9333
9334 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9335
9336 // First finger down on the window and the spy.
9337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9338 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9339 {100, 200}))
9340 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9341 spy->consumeMotionDown();
9342 window->consumeMotionDown();
9343
9344 // Spy window pilfers the pointers.
9345 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9346 window->consumeMotionCancel();
9347
9348 // Second finger down on the window and spy, but the window should not receive the pointer down.
9349 const MotionEvent secondFingerDownEvent =
9350 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9351 .displayId(ADISPLAY_ID_DEFAULT)
9352 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009353 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9354 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009355 .build();
9356 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9357 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9358 InputEventInjectionSync::WAIT_FOR_RESULT))
9359 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9360
Harry Cutts33476232023-01-30 19:57:29 +00009361 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009362
9363 // Third finger goes down outside all windows, so injection should fail.
9364 const MotionEvent thirdFingerDownEvent =
9365 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9366 .displayId(ADISPLAY_ID_DEFAULT)
9367 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009368 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9369 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9370 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009371 .build();
9372 ASSERT_EQ(InputEventInjectionResult::FAILED,
9373 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9374 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009375 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009376
9377 spy->assertNoEvents();
9378 window->assertNoEvents();
9379}
9380
9381/**
9382 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9383 */
9384TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9385 auto spy = createSpy();
9386 spy->setFrame(Rect(0, 0, 100, 100));
9387 auto window = createForeground();
9388 window->setFrame(Rect(0, 0, 200, 200));
9389
9390 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9391
9392 // First finger down on the window only
9393 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9394 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9395 {150, 150}))
9396 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9397 window->consumeMotionDown();
9398
9399 // Second finger down on the spy and window
9400 const MotionEvent secondFingerDownEvent =
9401 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9402 .displayId(ADISPLAY_ID_DEFAULT)
9403 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009404 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9405 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009406 .build();
9407 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9408 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9409 InputEventInjectionSync::WAIT_FOR_RESULT))
9410 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9411 spy->consumeMotionDown();
9412 window->consumeMotionPointerDown(1);
9413
9414 // Third finger down on the spy and window
9415 const MotionEvent thirdFingerDownEvent =
9416 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9417 .displayId(ADISPLAY_ID_DEFAULT)
9418 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009419 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9420 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9421 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009422 .build();
9423 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9424 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9425 InputEventInjectionSync::WAIT_FOR_RESULT))
9426 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9427 spy->consumeMotionPointerDown(1);
9428 window->consumeMotionPointerDown(2);
9429
9430 // Spy window pilfers the pointers.
9431 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9432 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9433 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9434
9435 spy->assertNoEvents();
9436 window->assertNoEvents();
9437}
9438
9439/**
9440 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9441 * other windows should be canceled. If this results in the cancellation of all pointers for some
9442 * window, then that window should receive ACTION_CANCEL.
9443 */
9444TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9445 auto spy = createSpy();
9446 spy->setFrame(Rect(0, 0, 100, 100));
9447 auto window = createForeground();
9448 window->setFrame(Rect(0, 0, 200, 200));
9449
9450 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9451
9452 // First finger down on both spy and window
9453 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9454 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9455 {10, 10}))
9456 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9457 window->consumeMotionDown();
9458 spy->consumeMotionDown();
9459
9460 // Second finger down on the spy and window
9461 const MotionEvent secondFingerDownEvent =
9462 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9463 .displayId(ADISPLAY_ID_DEFAULT)
9464 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009465 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9466 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009467 .build();
9468 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9469 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9470 InputEventInjectionSync::WAIT_FOR_RESULT))
9471 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9472 spy->consumeMotionPointerDown(1);
9473 window->consumeMotionPointerDown(1);
9474
9475 // Spy window pilfers the pointers.
9476 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9477 window->consumeMotionCancel();
9478
9479 spy->assertNoEvents();
9480 window->assertNoEvents();
9481}
9482
9483/**
9484 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9485 * be sent to other windows
9486 */
9487TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9488 auto spy = createSpy();
9489 spy->setFrame(Rect(0, 0, 100, 100));
9490 auto window = createForeground();
9491 window->setFrame(Rect(0, 0, 200, 200));
9492
9493 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9494
9495 // First finger down on both window and spy
9496 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9497 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9498 {10, 10}))
9499 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9500 window->consumeMotionDown();
9501 spy->consumeMotionDown();
9502
9503 // Spy window pilfers the pointers.
9504 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9505 window->consumeMotionCancel();
9506
9507 // Second finger down on the window only
9508 const MotionEvent secondFingerDownEvent =
9509 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9510 .displayId(ADISPLAY_ID_DEFAULT)
9511 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009512 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9513 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009514 .build();
9515 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9516 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9517 InputEventInjectionSync::WAIT_FOR_RESULT))
9518 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9519 window->consumeMotionDown();
9520 window->assertNoEvents();
9521
9522 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9523 spy->consumeMotionMove();
9524 spy->assertNoEvents();
9525}
9526
Prabir Pradhand65552b2021-10-07 11:23:50 -07009527class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9528public:
9529 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9530 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9531 std::make_shared<FakeApplicationHandle>();
9532 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009533 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9534 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009535 overlay->setFocusable(false);
9536 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009537 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009538 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009539 overlay->setTrustedOverlay(true);
9540
9541 std::shared_ptr<FakeApplicationHandle> application =
9542 std::make_shared<FakeApplicationHandle>();
9543 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009544 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9545 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009546 window->setFocusable(true);
9547 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009548
9549 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9550 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9551 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009552 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009553 return {std::move(overlay), std::move(window)};
9554 }
9555
9556 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009557 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009558 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009559 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009560 }
9561
9562 void sendStylusEvent(int32_t action) {
9563 NotifyMotionArgs motionArgs =
9564 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9565 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009566 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009567 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009568 }
9569};
9570
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009571using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9572
9573TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
9574 ScopedSilentDeath _silentDeath;
9575
Prabir Pradhand65552b2021-10-07 11:23:50 -07009576 auto [overlay, window] = setupStylusOverlayScenario();
9577 overlay->setTrustedOverlay(false);
9578 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9579 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9580 ".* not a trusted overlay");
9581}
9582
9583TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9584 auto [overlay, window] = setupStylusOverlayScenario();
9585 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9586
9587 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9588 overlay->consumeMotionDown();
9589 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9590 overlay->consumeMotionUp();
9591
9592 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9593 window->consumeMotionDown();
9594 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9595 window->consumeMotionUp();
9596
9597 overlay->assertNoEvents();
9598 window->assertNoEvents();
9599}
9600
9601TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9602 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009603 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009604 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9605
9606 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9607 overlay->consumeMotionDown();
9608 window->consumeMotionDown();
9609 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9610 overlay->consumeMotionUp();
9611 window->consumeMotionUp();
9612
9613 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9614 window->consumeMotionDown();
9615 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9616 window->consumeMotionUp();
9617
9618 overlay->assertNoEvents();
9619 window->assertNoEvents();
9620}
9621
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009622/**
9623 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9624 * The scenario is as follows:
9625 * - The stylus interceptor overlay is configured as a spy window.
9626 * - The stylus interceptor spy receives the start of a new stylus gesture.
9627 * - It pilfers pointers and then configures itself to no longer be a spy.
9628 * - The stylus interceptor continues to receive the rest of the gesture.
9629 */
9630TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9631 auto [overlay, window] = setupStylusOverlayScenario();
9632 overlay->setSpy(true);
9633 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9634
9635 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9636 overlay->consumeMotionDown();
9637 window->consumeMotionDown();
9638
9639 // The interceptor pilfers the pointers.
9640 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9641 window->consumeMotionCancel();
9642
9643 // The interceptor configures itself so that it is no longer a spy.
9644 overlay->setSpy(false);
9645 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9646
9647 // It continues to receive the rest of the stylus gesture.
9648 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9649 overlay->consumeMotionMove();
9650 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9651 overlay->consumeMotionUp();
9652
9653 window->assertNoEvents();
9654}
9655
Prabir Pradhan5735a322022-04-11 17:23:34 +00009656struct User {
9657 int32_t mPid;
9658 int32_t mUid;
9659 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9660 std::unique_ptr<InputDispatcher>& mDispatcher;
9661
9662 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
9663 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9664
9665 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9666 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9667 ADISPLAY_ID_DEFAULT, {100, 200},
9668 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9669 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9670 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9671 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9672 }
9673
9674 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009675 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009676 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009677 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009678 mPolicyFlags);
9679 }
9680
9681 sp<FakeWindowHandle> createWindow() const {
9682 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9683 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009684 sp<FakeWindowHandle> window =
9685 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9686 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009687 window->setOwnerInfo(mPid, mUid);
9688 return window;
9689 }
9690};
9691
9692using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9693
9694TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
9695 auto owner = User(mDispatcher, 10, 11);
9696 auto window = owner.createWindow();
9697 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9698
9699 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9700 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9701 window->consumeMotionDown();
9702
9703 setFocusedWindow(window);
9704 window->consumeFocusEvent(true);
9705
9706 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9707 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9708 window->consumeKeyDown(ADISPLAY_ID_NONE);
9709}
9710
9711TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
9712 auto owner = User(mDispatcher, 10, 11);
9713 auto window = owner.createWindow();
9714 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9715
9716 auto rando = User(mDispatcher, 20, 21);
9717 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9718 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9719
9720 setFocusedWindow(window);
9721 window->consumeFocusEvent(true);
9722
9723 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9724 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9725 window->assertNoEvents();
9726}
9727
9728TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
9729 auto owner = User(mDispatcher, 10, 11);
9730 auto window = owner.createWindow();
9731 auto spy = owner.createWindow();
9732 spy->setSpy(true);
9733 spy->setTrustedOverlay(true);
9734 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9735
9736 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9737 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9738 spy->consumeMotionDown();
9739 window->consumeMotionDown();
9740}
9741
9742TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
9743 auto owner = User(mDispatcher, 10, 11);
9744 auto window = owner.createWindow();
9745
9746 auto rando = User(mDispatcher, 20, 21);
9747 auto randosSpy = rando.createWindow();
9748 randosSpy->setSpy(true);
9749 randosSpy->setTrustedOverlay(true);
9750 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9751
9752 // The event is targeted at owner's window, so injection should succeed, but the spy should
9753 // not receive the event.
9754 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9755 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9756 randosSpy->assertNoEvents();
9757 window->consumeMotionDown();
9758}
9759
9760TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
9761 auto owner = User(mDispatcher, 10, 11);
9762 auto window = owner.createWindow();
9763
9764 auto rando = User(mDispatcher, 20, 21);
9765 auto randosSpy = rando.createWindow();
9766 randosSpy->setSpy(true);
9767 randosSpy->setTrustedOverlay(true);
9768 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9769
9770 // A user that has injection permission can inject into any window.
9771 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9772 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9773 ADISPLAY_ID_DEFAULT));
9774 randosSpy->consumeMotionDown();
9775 window->consumeMotionDown();
9776
9777 setFocusedWindow(randosSpy);
9778 randosSpy->consumeFocusEvent(true);
9779
9780 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9781 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9782 window->assertNoEvents();
9783}
9784
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009785TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00009786 auto owner = User(mDispatcher, 10, 11);
9787 auto window = owner.createWindow();
9788
9789 auto rando = User(mDispatcher, 20, 21);
9790 auto randosWindow = rando.createWindow();
9791 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9792 randosWindow->setWatchOutsideTouch(true);
9793 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9794
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009795 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009796 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9797 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9798 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009799 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +00009800}
9801
Garfield Tane84e6f92019-08-29 17:28:41 -07009802} // namespace android::inputdispatcher